您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Golang基礎(chǔ)的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
package main import "fmt" func main() { fmt.Println("hello golang") }
布爾型( true 或者 false)
數(shù)字類型( 整型 int 和 浮點(diǎn)型 float32、float64 )
字符串類型( 字符串就是一串固定長(zhǎng)度的字符連接起來(lái)的字符序列 )
派生類型:
指針類型(Pointer)
數(shù)組類型
結(jié)構(gòu)化類型(struct)
Channel 類型
函數(shù)類型
切片類型
接口類型(interface)
Map 類型
整形
uint8 無(wú)符號(hào) 8 位整型 (0 到 255)
uint16 無(wú)符號(hào) 16 位整型 (0 到 65535)
uint32 無(wú)符號(hào) 32 位整型 (0 到 4294967295)
uint64 無(wú)符號(hào) 64 位整型 (0 到 18446744073709551615)
int8 有符號(hào) 8 位整型 (-128 到 127)
int16 有符號(hào) 16 位整型 (-32768 到 32767)
int32 有符號(hào) 32 位整型 (-2147483648 到 2147483647)
int64 有符號(hào) 64 位整型 (-9223372036854775808 到 9223372036854775807)
浮點(diǎn)型
float32 32位浮點(diǎn)型數(shù)
float64 64位浮點(diǎn)型數(shù)
complex64 32 位實(shí)數(shù)和虛數(shù)
complex128 64 位實(shí)數(shù)和虛數(shù)
其他數(shù)字類型
byte 類似 uint8
rune 類似 int32
uint 32 或 64 位
int 與 uint 一樣大小
uintptr 無(wú)符號(hào)整型,用于存放一個(gè)指針
// 聲明一個(gè)變量 var identifier type // 可以一次聲明多個(gè)變量 var identifier1, identifier2 type // 根據(jù)值自行判定變量類型 var v_name = value // 簡(jiǎn)短形式 省略 var, 注意 := 左側(cè)如果沒(méi)有聲明新的變量 v_name := value
// 聲明一個(gè)常量 const identifier [type] = value // 顯式類型定義 const b string = "abc" // 隱式類型定義 const b = "abc" // 多個(gè)相同類型的聲明(隱式類型定義) const c_name1, c_name2 = value1, value2
iota,特殊常量,可以認(rèn)為是一個(gè)可以被編譯器修改的常量
iota 在 const關(guān)鍵字出現(xiàn)時(shí)將被重置為 0(const 內(nèi)部的第一行之前),const 中每新增一行常量聲明將使 iota 計(jì)數(shù)一次(iota 可理解為 const 語(yǔ)句塊中的行索引)。
iota 可以被用作枚舉值
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //獨(dú)立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢復(fù)計(jì)數(shù) i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
運(yùn)行結(jié)果
0 1 2 ha ha 100 100 7 8
第一個(gè) iota 等于 0,每當(dāng) iota 在新的一行被使用時(shí),它的值都會(huì)自動(dòng)加 1
package main import "fmt" func main() { var a = 12 if a > 10 { fmt.Println("a>10") } else { fmt.Println("a<=10") } }
運(yùn)行結(jié)果
a>10
package main import "fmt" func main() { var a = 12 switch a { case 1: fmt.Println(1) case 2: fmt.Println(2) case 12: fmt.Println(12) default: fmt.Println(a) } }
運(yùn)行結(jié)果
12
使用 fallthrough 會(huì)強(qiáng)制執(zhí)行后面的 case 語(yǔ)句,fallthrough 不會(huì)判斷下一條 case 的表達(dá)式結(jié)果是否為 true
package main import "fmt" func main() { var a = 1 switch a { case 1: fmt.Println(1) fallthrough case 2: fmt.Println(2) case 12: fmt.Println(12) default: fmt.Println(a) } }
運(yùn)行結(jié)果
1 2
select 是 Go 中的一個(gè)控制結(jié)構(gòu),類似于用于通信的 switch 語(yǔ)句。每個(gè) case 必須是一個(gè)通信操作,要么是發(fā)送要么是接收。
select 隨機(jī)執(zhí)行一個(gè)可運(yùn)行的 case。如果沒(méi)有 case 可運(yùn)行,它將阻塞,直到有 case 可運(yùn)行。一個(gè)默認(rèn)的子句應(yīng)該總是可運(yùn)行的。
package main import "fmt" func main() { var c1, c2, c3 chan int var i1, i2 int select { case i1 = <-c1: fmt.Printf("received ", i1, " from c1\n") case c2 <- i2: fmt.Printf("sent ", i2, " to c2\n") case i3, ok := <-c3: if ok { fmt.Printf("received ", i3, " from c3\n") } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("no communication\n") } }
運(yùn)行結(jié)果
no communication
package main import "fmt" func main() { for i := 1; i < 10; i++ { fmt.Println(i) } }
package main import "fmt" func main() { var i = 1 for i < 10 { fmt.Println(i) i++ } }
運(yùn)行結(jié)果
1 2 3 4 5 6 7 8 9
死循環(huán)
for { }
package main import "fmt" func main() { test(1) } func test(i int) int { for i < 10 { fmt.Println(i) i++ } return i }
運(yùn)行結(jié)果
1 2 3 4 5 6 7 8 9
package main import "fmt" func main() { i := test(1, 9) fmt.Println("最大值為:", i) } func test(i, j int) int { if i > j { return i } else { return j } }
運(yùn)行結(jié)果
最大值為: 9
package main import "fmt" func main() { s, s2 := test("hello", "go") fmt.Println(s, s2) } func test(i, j string) (string, string) { return i, j }
運(yùn)行結(jié)果
hello go
package main import "fmt" func main() { var a = 3 var b = 4 fmt.Println("值傳遞運(yùn)行前a=", a, "b=", b) test1(a, b) fmt.Println("值傳遞運(yùn)行后a=", a, "b=", b) fmt.Println("===============================================") var i = 1 var j = 2 fmt.Println("引用傳遞運(yùn)行前i=", i, "j=", j) test2(&i, &j) fmt.Println("引用傳遞運(yùn)行后i=", i, "j=", j) } // 值傳遞 func test1(i, j int) (int, int) { var temp int temp = i i = j j = temp return i, j } // 引用傳遞 func test2(i, j *int) (int, int) { var temp int temp = *i *i = *j *j = temp return *i, *j }
運(yùn)行結(jié)果
值傳遞運(yùn)行前a= 3 b= 4 值傳遞運(yùn)行后a= 3 b= 4 =============================================== 引用傳遞運(yùn)行前i= 1 j= 2 引用傳遞運(yùn)行后i= 2 j= 1
package main import "fmt" func main() { funcA := func(a int) int { return a } fmt.Println(funcA(12)) }
運(yùn)行結(jié)果
12
Go 語(yǔ)言支持匿名函數(shù),可作為閉包。匿名函數(shù)是一個(gè)"內(nèi)聯(lián)"語(yǔ)句或表達(dá)式。匿名函數(shù)的優(yōu)越性在于可以直接使用函數(shù)內(nèi)的變量,不必申明。
package main import "fmt" func main() { next := getSequence() fmt.Println(next()) fmt.Println(next()) fmt.Println(next()) } func getSequence() func() int { a := 1 return func() int { a++ return a } }
運(yùn)行結(jié)果
2 3 4
Go 語(yǔ)言中同時(shí)有函數(shù)和方法。一個(gè)方法就是一個(gè)包含了接受者的函數(shù),接受者可以是命名類型或者結(jié)構(gòu)體類型的一個(gè)值或者是一個(gè)指針。所有給定類型的方法屬于該類型的方法集
package main import "fmt" type Circle struct { radius float64 } func (circle Circle) getPerimeter() float64 { return 3.14 * circle.radius * 2 } func main() { var circle Circle circle.radius = 10 fmt.Println(circle.getPerimeter()) }
運(yùn)行結(jié)果
62.800000000000004
Go 語(yǔ)言中變量可以在三個(gè)地方聲明:
函數(shù)內(nèi)定義的變量稱為局部變量
函數(shù)外定義的變量稱為全局變量
函數(shù)定義中的變量稱為形式參數(shù)
package main import "fmt" // 全局變量 var a = 1 func main() { // 局部變量 var b = 2 test(a) test(b) } // 形式參數(shù) func test(a int) { fmt.Println(a) }
數(shù)組是具有相同唯一類型的一組已編號(hào)且長(zhǎng)度固定的數(shù)據(jù)項(xiàng)序列,這種類型可以是任意的原始類型例如整形、字符串或者自定義類型
// 形式 var variable_name [SIZE] variable_type // 舉例 var balance [10] float32
// 初始化一個(gè)長(zhǎng)度為5的float32數(shù)組 var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} // 如果忽略 [] 中的數(shù)字不設(shè)置數(shù)組大小 var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} balance[6] = 60.0
var a float32 = balance[5]
一個(gè)指針變量指向了一個(gè)值的內(nèi)存地址
// 形式 var var_name *var-type // 舉例 var ip *int /* 指向整型*/ var fp *float32 /* 指向浮點(diǎn)型 */
package main import "fmt" func main() { var a int = 20 /* 聲明實(shí)際變量 */ var ip *int /* 聲明指針變量 */ ip = &a /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("a 變量的地址是: %x\n", &a) /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("ip 變量?jī)?chǔ)存的指針地址: %x\n", ip) /* 使用指針訪問(wèn)值 */ fmt.Printf("*ip 變量的值: %d\n", *ip) }
運(yùn)行結(jié)果
a 變量的地址是: c00000a0b0 ip 變量?jī)?chǔ)存的指針地址: c00000a0b0 *ip 變量的值: 20
當(dāng)一個(gè)指針被定義后沒(méi)有分配到任何變量時(shí),它的值為 nil。
nil 指針也稱為空指針。一個(gè)指針變量通??s寫(xiě)為 ptr。
package main import "fmt" func main() { var ip *int /* 聲明指針變量 */ /* 指針變量的存儲(chǔ)地址 */ fmt.Printf("ip 的值為: %x\n", ip) }
運(yùn)行結(jié)果
ip 的值為: 0
if(ptr != nil) /* ptr 不是空指針 */ if(ptr == nil) /* ptr 是空指針 */
package main import "fmt" func main() { a := []int{10, 100, 200} // 遍歷數(shù)組 for i := 0; i < len(a); i++ { fmt.Printf("a[%d] = %d\n", i, a[i]) } fmt.Println("==================================") // 有一種情況,我們可能需要保存數(shù)組,這樣我們就需要使用到指針。 // 以下聲明了整型指針數(shù)組: var ptr [3]*int for i := 0; i < len(a); i++ { /* 整數(shù)地址賦值給指針數(shù)組 */ ptr[i] = &a[i] } for i := 0; i < len(ptr); i++ { fmt.Printf("a[%d] = %d\n", i, *ptr[i]) } }
運(yùn)行結(jié)果
a[0] = 10 a[1] = 100 a[2] = 200 ================================== a[0] = 10 a[1] = 100 a[2] = 200
如果一個(gè)指針變量存放的又是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針變量。 指向指針的指針變量聲明格式
var ptr **int;
package main import "fmt" func main() { var a int var ptr *int var pptr **int a = 3000 /* 指針 ptr 地址 */ ptr = &a /* 指向指針 ptr 地址 */ pptr = &ptr /* 獲取 pptr 的值 */ fmt.Printf("變量 a = %d\n", a) fmt.Printf("指針變量 *ptr = %d\n", *ptr) fmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr) }
運(yùn)行結(jié)果
變量 a = 3000 指針變量 *ptr = 3000 指向指針的指針變量 **pptr = 3000
package main import "fmt" func main() { var a = 3 var b = 4 fmt.Println("值傳遞運(yùn)行前a=", a, "b=", b) test1(a, b) fmt.Println("值傳遞運(yùn)行后a=", a, "b=", b) fmt.Println("===============================================") var i = 1 var j = 2 fmt.Println("引用傳遞運(yùn)行前i=", i, "j=", j) test2(&i, &j) fmt.Println("引用傳遞運(yùn)行后i=", i, "j=", j) } // 值傳遞 func test1(i, j int) (int, int) { var temp int temp = i i = j j = temp return i, j } // 引用傳遞 func test2(i, j *int) (int, int) { var temp int temp = *i *i = *j *j = temp return *i, *j }
運(yùn)行結(jié)果
值傳遞運(yùn)行前a= 3 b= 4 值傳遞運(yùn)行后a= 3 b= 4 =============================================== 引用傳遞運(yùn)行前i= 1 j= 2 引用傳遞運(yùn)行后i= 2 j= 1
結(jié)構(gòu)體是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合。
結(jié)構(gòu)體表示一項(xiàng)記錄,比如保存圖書(shū)館的書(shū)籍記錄,每本書(shū)有以下屬性:
Title :標(biāo)題 Author : 作者 Subject:學(xué)科 ID:書(shū)籍ID
type struct_variable_type struct { member definition member definition ... member definition }
一旦定義了結(jié)構(gòu)體類型,它就能用于變量的聲明,語(yǔ)法格式如下:
variable_name := structure_variable_type {value1, value2...valuen} 或 variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
package main import "fmt" // 一、定義結(jié)構(gòu)體 type Books struct { title string author string subject string book_id int } func main() { // 創(chuàng)建一個(gè)新的結(jié)構(gòu)體 fmt.Println(Books{"Go 語(yǔ)言", "Google", "Go 語(yǔ)言教程", 6495407}) // 也可以使用 key => value 格式 fmt.Println(Books{title: "Go 語(yǔ)言", author: "Google", subject: "Go 語(yǔ)言教程", book_id: 6495407}) // 忽略的字段為 0 或 空 fmt.Println(Books{title: "Go 語(yǔ)言", author: "Google"}) fmt.Println("=========================") // 二、訪問(wèn)結(jié)構(gòu)體成員 /* book 2 描述 */ var Book2 Books Book2.title = "Python 教程" Book2.author = "Python" Book2.subject = "Python 語(yǔ)言教程" Book2.book_id = 6495700 /* 打印 Book2 信息 */ fmt.Printf("Book 2 title : %s\n", Book2.title) fmt.Printf("Book 2 author : %s\n", Book2.author) fmt.Printf("Book 2 subject : %s\n", Book2.subject) fmt.Printf("Book 2 book_id : %d\n", Book2.book_id) fmt.Println("=========================") // 三、結(jié)構(gòu)體作為函數(shù)參數(shù) printBook(Book2) fmt.Println("=========================") // 四、結(jié)構(gòu)體指針 printBook2(&Book2) } func printBook(book Books) { fmt.Printf("Book title : %s\n", book.title) fmt.Printf("Book author : %s\n", book.author) fmt.Printf("Book subject : %s\n", book.subject) fmt.Printf("Book book_id : %d\n", book.book_id) } func printBook2(book *Books) { fmt.Printf("Book title : %s\n", book.title) fmt.Printf("Book author : %s\n", book.author) fmt.Printf("Book subject : %s\n", book.subject) fmt.Printf("Book book_id : %d\n", book.book_id) }
運(yùn)行結(jié)果
{Go 語(yǔ)言 Google Go 語(yǔ)言教程 6495407} {Go 語(yǔ)言 Google Go 語(yǔ)言教程 6495407} {Go 語(yǔ)言 Google 0} ========================= Book 2 title : Python 教程 Book 2 author : Python Book 2 subject : Python 語(yǔ)言教程 Book 2 book_id : 6495700 ========================= Book title : Python 教程 Book author : Python Book subject : Python 語(yǔ)言教程 Book book_id : 6495700 ========================= Book title : Python 教程 Book author : Python Book subject : Python 語(yǔ)言教程 Book book_id : 6495700
Go 數(shù)組的長(zhǎng)度不可改變,與數(shù)組相比切片的長(zhǎng)度是不固定的,可以追加元素,在追加時(shí)可能使切片的容量增大。
var identifier []type
var slice1 []type = make([]type, len) 或者簡(jiǎn)寫(xiě) slice1 := make([]type, len) 指定長(zhǎng)度
make([]T, length, capacity) 指定容量
package main import "fmt" func main() { // 切片初始化 var slice = []int{1, 2, 3} // 從下標(biāo)startIndex到endIndex-1 下的元素 切片截取 fmt.Println(slice[0:2]) fmt.Println(slice[:2]) fmt.Println(slice[0:]) fmt.Println("=======================") // len() 和 cap() 函數(shù) fmt.Printf("len=%d cap=%d slice=%v\n", len(slice), cap(slice), slice) fmt.Println("=======================") // 空切片 var numbers []int fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers), cap(numbers), numbers) if numbers == nil { fmt.Printf("切片是空的\n") } fmt.Println("=======================") // append() 和 copy() 函數(shù) var numbers1 []int // append() 追加 numbers1 = append(numbers1, 1) numbers1 = append(numbers1, 2, 3, 4) fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers1), cap(numbers1), numbers1) fmt.Println("=======================") // copy() 復(fù)制 /* 創(chuàng)建切片 numbers2 是之前切片的兩倍容量*/ numbers2 := make([]int, len(numbers1), (cap(numbers1))*2) /* 拷貝 numbers1 的內(nèi)容到 numbers2 */ copy(numbers2, numbers1) fmt.Printf("len=%d cap=%d slice=%v\n", len(numbers2), cap(numbers2), numbers2) }
運(yùn)行結(jié)果
[1 2] [1 2] [1 2 3] ======================= len=3 cap=3 slice=[1 2 3] ======================= len=0 cap=0 slice=[] 切片是空的 ======================= len=4 cap=4 slice=[1 2 3 4] ======================= len=4 cap=8 slice=[1 2 3 4]
package main import "fmt" func main() { //這是我們使用range去求一個(gè)slice的和。使用數(shù)組跟這個(gè)很類似 nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum) //在數(shù)組上使用range將傳入index和值兩個(gè)變量。上面那個(gè)例子我們不需要使用該元素的序號(hào),所以我們使用空白符"_"省略了。有時(shí)侯我們確實(shí)需要知道它的索引。 for i, num := range nums { if num == 3 { fmt.Println("index:", i) } } //range也可以用在map的鍵值對(duì)上。 kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %s\n", k, v) } //range也可以用來(lái)枚舉Unicode字符串。第一個(gè)參數(shù)是字符的索引,第二個(gè)是字符(Unicode的值)本身。 for i, c := range "go" { fmt.Println(i, c) } }
運(yùn)行結(jié)果
sum: 9 index: 1 a -> apple b -> banana 0 103 1 111
Map 是一種無(wú)序的鍵值對(duì)的集合。Map 最重要的一點(diǎn)是通過(guò) key 來(lái)快速檢索數(shù)據(jù),key 類似于索引,指向數(shù)據(jù)的值。
/* 聲明變量,默認(rèn) map 是 nil */ var map_variable map[key_data_type]value_data_type /* 使用 make 函數(shù) */ map_variable := make(map[key_data_type]value_data_type)
如果不初始化 map,那么就會(huì)創(chuàng)建一個(gè) nil map。nil map 不能用來(lái)存放鍵值對(duì)
package main import "fmt" func main() { var countryCapitalMap = make(map[string]string) /* map插入key - value對(duì),各個(gè)國(guó)家對(duì)應(yīng)的首都 */ countryCapitalMap["France"] = "巴黎" countryCapitalMap["Italy"] = "羅馬" countryCapitalMap["Japan"] = "東京" countryCapitalMap["India "] = "新德里" /*使用鍵輸出地圖值 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } /*查看元素在集合中是否存在 */ capital, ok := countryCapitalMap["American"] /*如果確定是真實(shí)的,則存在,否則不存在 */ /*fmt.Println(capital) */ /*fmt.Println(ok) */ if ok { fmt.Println("American 的首都是", capital) } else { fmt.Println("American 的首都不存在") } fmt.Println("========================") // delete() 函數(shù) for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } // 刪除元素 delete(countryCapitalMap, "France") fmt.Println("法國(guó)條目被刪除") for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap[country]) } }
運(yùn)行結(jié)果
France 首都是 巴黎 Italy 首都是 羅馬 Japan 首都是 東京 India 首都是 新德里 American 的首都不存在 ======================== India 首都是 新德里 France 首都是 巴黎 Italy 首都是 羅馬 Japan 首都是 東京 法國(guó)條目被刪除 Japan 首都是 東京 India 首都是 新德里 Italy 首都是 羅馬
遞歸,就是在運(yùn)行的過(guò)程中調(diào)用自己
package main import "fmt" func main() { var i int = 15 fmt.Printf("%d 的階乘是 %d\n", i, Factorial(uint64(i))) } func Factorial(n uint64) (result uint64) { if n > 0 { result = n * Factorial(n-1) return result } return 1 }
運(yùn)行結(jié)果
15 的階乘是 1307674368000
package main import "fmt" func main() { var i int for i = 0; i < 10; i++ { fmt.Printf("%d\t", fibonacci(i)) } } func fibonacci(n int) int { if n < 2 { return n } return fibonacci(n-2) + fibonacci(n-1) }
運(yùn)行結(jié)果
0 1 1 2 3 5 8 13 21 34
類型轉(zhuǎn)換用于將一種數(shù)據(jù)類型的變量轉(zhuǎn)換為另外一種類型的變量。
type_name(expression)
package main import "fmt" func main() { var sum int = 17 var count int = 5 var mean float32 mean = float32(sum) / float32(count) fmt.Printf("mean 的值為: %f\n", mean) }
運(yùn)行結(jié)果
mean 的值為: 3.400000
package main import "fmt" type Phone interface { call() } type NokiaPhone struct { } type IPhone struct { } func main() { n := new(NokiaPhone) n.call() i := new(IPhone) i.call() } func (NokiaPhone) call() { fmt.Println("nokiaPhone") } func (IPhone) call() { fmt.Println("IPhone") }
運(yùn)行結(jié)果
nokiaPhone IPhone
Go 語(yǔ)言通過(guò)內(nèi)置的錯(cuò)誤接口提供了非常簡(jiǎn)單的錯(cuò)誤處理機(jī)制。
error類型是一個(gè)接口類型,這是它的定義
type error interface { Error() string }
我們可以在編碼中通過(guò)實(shí)現(xiàn) error 接口類型來(lái)生成錯(cuò)誤信息。
函數(shù)通常在最后的返回值中返回錯(cuò)誤信息。使用errors.New 可返回一個(gè)錯(cuò)誤信息
package main import ( "errors" "fmt" ) func main() { _, err := Sqrt(-1) if err != nil { fmt.Println(err) } } func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("math: square root of negative number") } // 實(shí)現(xiàn) return f, nil }
運(yùn)行結(jié)果
math: square root of negative number
Go 語(yǔ)言支持并發(fā),我們只需要通過(guò) go 關(guān)鍵字來(lái)開(kāi)啟 goroutine 即可。
goroutine 是輕量級(jí)線程,goroutine 的調(diào)度是由 Golang 運(yùn)行時(shí)進(jìn)行管理的。
goroutine 語(yǔ)法格式:
go 函數(shù)名( 參數(shù)列表 )
Go 允許使用 go 語(yǔ)句開(kāi)啟一個(gè)新的運(yùn)行期線程, 即 goroutine,以一個(gè)不同的、新創(chuàng)建的 goroutine 來(lái)執(zhí)行一個(gè)函數(shù)。 同一個(gè)程序中的所有 goroutine 共享同一個(gè)地址空間。
package main import ( "fmt" "time" ) func main() { go say("world") say("hello") } func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } }
運(yùn)行結(jié)果
hello world world hello hello world world hello hello
通道(channel)是用來(lái)傳遞數(shù)據(jù)的一個(gè)數(shù)據(jù)結(jié)構(gòu)。
通道可用于兩個(gè) goroutine 之間通過(guò)傳遞一個(gè)指定類型的值來(lái)同步運(yùn)行和通訊。操作符 <- 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。 聲明一個(gè)通道,通道在使用前必須先創(chuàng)建:
ch := make(chan int)
注意:默認(rèn)情況下,通道是不帶緩沖區(qū)的。發(fā)送端發(fā)送數(shù)據(jù),同時(shí)必須有接收端相應(yīng)的接收數(shù)據(jù)。
package main import ( "fmt" ) func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // 從通道 c 中接收 fmt.Println(x, y, x+y) } func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // 把 sum 發(fā)送到通道 c }
運(yùn)行結(jié)果
-5 17 12
通道可以設(shè)置緩沖區(qū),通過(guò) make 的第二個(gè)參數(shù)指定緩沖區(qū)大小:
ch := make(chan int, 100)
帶緩沖區(qū)的通道允許發(fā)送端的數(shù)據(jù)發(fā)送和接收端的數(shù)據(jù)獲取處于異步狀態(tài),就是說(shuō)發(fā)送端發(fā)送的數(shù)據(jù)可以放在緩沖區(qū)里面,可以等待接收端去獲取數(shù)據(jù),而不是立刻需要接收端去獲取數(shù)據(jù)。
不過(guò)由于緩沖區(qū)的大小是有限的,所以還是必須有接收端來(lái)接收數(shù)據(jù)的,否則緩沖區(qū)一滿,數(shù)據(jù)發(fā)送端就無(wú)法再發(fā)送數(shù)據(jù)了。
注意:如果通道不帶緩沖,發(fā)送方會(huì)阻塞直到接收方從通道中接收了值。如果通道帶緩沖,發(fā)送方則會(huì)阻塞直到發(fā)送的值被拷貝到緩沖區(qū)內(nèi);如果緩沖區(qū)已滿,則意味著需要等待直到某個(gè)接收方獲取到一個(gè)值。接收方在有值可以接收之前會(huì)一直阻塞。
package main import ( "fmt" ) func main() { // 這里我們定義了一個(gè)可以存儲(chǔ)整數(shù)類型的帶緩沖通道 // 緩沖區(qū)大小為2 ch := make(chan int, 2) // 因?yàn)?nbsp;ch 是帶緩沖的通道,我們可以同時(shí)發(fā)送兩個(gè)數(shù)據(jù) // 而不用立刻需要去同步讀取數(shù)據(jù) ch <- 1 ch <- 2 // 獲取這兩個(gè)數(shù)據(jù) fmt.Println(<-ch) fmt.Println(<-ch) }
運(yùn)行結(jié)果
1 2
Go 通過(guò) range 關(guān)鍵字來(lái)實(shí)現(xiàn)遍歷讀取到的數(shù)據(jù),類似于與數(shù)組或切片。格式如下:
v, ok := <-ch
package main import ( "fmt" ) func main() { c := make(chan int, 10) go fibonacci(cap(c), c) // range 函數(shù)遍歷每個(gè)從通道接收到的數(shù)據(jù),因?yàn)?nbsp;c 在發(fā)送完 10 個(gè) // 數(shù)據(jù)之后就關(guān)閉了通道,所以這里我們 range 函數(shù)在接收到 10 個(gè)數(shù)據(jù) // 之后就結(jié)束了。如果上面的 c 通道不關(guān)閉,那么 range 函數(shù)就不 // 會(huì)結(jié)束,從而在接收第 11 個(gè)數(shù)據(jù)的時(shí)候就阻塞了。 for i := range c { fmt.Println(i) } } func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } // 關(guān)閉通道 close(c) }
運(yùn)行結(jié)果
0 1 1 2 3 5 8 13 21 34
關(guān)于“Golang基礎(chǔ)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。