前面講的都是一些Go 語言的基礎知識,感興趣的朋友可以先看看之前的文章。https://www.cnblogs.com/zhangweizhong/category/1275863.html。
今天就來講講go 里面的高級功能,也是go語言重要的特性:Go協程(Goroutine)。
什么是Go協程
Go協程(Goroutine)是與其他函數同時運行的函數。可以認為Go協程是輕量級的線程,由Go運行時來管理。
在函數調用前加上go關鍵字,這次調用就會在一個新的goroutine中並發執行。當被調用的函數返回時,這個goroutine也自動結束。聽着感覺像C# 中的Task。
需要注意的是,如果這個函數有返回值,那么這個返回值會被丟棄。
Go 協程(Goroutine)之間通過信道(channel)進行通信,簡單的說就是多個協程之間通信的管道。信道可以防止多個協程訪問共享內存時發生資源爭搶的問題。
如何使用
package main import ( "fmt" "time" ) func hello() { fmt.Println("Hello world goroutine") } func main() { go hello() time.Sleep(1 * time.Second) fmt.Println("main function") }
Channel(管道)
Channel(管道) 可以被認為是協程之間通信的管道。與水流從管道的一端流向另一端一樣,數據可以從信道的一端發送並在另一端接收。
1. 定義
每個channel都有一個類型。此類型是允許信道傳輸的數據類型。channel是類型相關的,一個channel只能傳遞一種類型的值,這個類型需要在聲明channel時指定。
2. 聲明
a. 我們需要通過內置函數 make 來創建一個信道。
下面的代碼聲明了一個信道:
var ch chan int
b. 與其他變量定義一樣,快速聲明也是定義信道的一種有效而簡潔的方式:
a := make(chan int)
c. 創建一個帶緩沖的channel
c := make(chan int, 1024) // 從帶緩沖的channel中讀數據 for i:=range c { ... }
3. 發送和接收數據
通過信道發送和接收數據的語法如下:
data := <- a // 從channel a 讀取數據 a <- data // 將數據寫入到 channel a
箭頭的指向說明了數據是發送還是接收。
完整例子
下面就直接說說,Goroutine和channel 共同使用的完整例子:
package main import ( "fmt" "time" ) func Producer(queue chan<- int) { for i := 0; i < 10; i++ { queue <- i //寫入 fmt.Println("create :", i) } } func Consumer(queue <-chan int) { for i := 0; i < 10; i++ { v := <-queue // 讀出 fmt.Println("receive:", v) } } func main() { queue := make(chan int, 88) go Producer(queue) go Consumer(queue) time.Sleep(1 * time.Second) }
最后
以上,就簡單的介紹了Go語言中的協程(Goroutine)和信道(channel)。這兩個功能特性,是go語言中重要的特性。大家可以寫寫其他的例子,熟悉掌握。
