golang開發中channel使用
channel[通道]是golang的一種重要特性,正是因為channel的存在才使得golang不同於其它語言。channel使得併發程式設計變得簡單容易有趣。
channel的概念和語法
一個channel可以理解為一個先進先出的訊息佇列。channel用來在協程[goroutine]之前傳遞資料,準確的說,是用來傳遞資料的所有權。一個設計良好的程式應該確保同一時刻channel裡面的資料只會被同一個協程擁有,這樣就可以避免併發帶來的資料不安全問題[data races]。
正文
channel主要是用於多個goroutine之間通訊
channel語法
channel是引用型別,需要實用make來建立channel,如下
chan Type 通道的型別
buffer 是可選引數,代表通道緩衝區的大小(省略則代表無緩衝)
向channel裡面寫入資料使用 <- 符號
q := make(chan bool) q<-true
從channel裡面讀取資料也是使用 <- 符號,只不過寫入的channel在右邊,讀取的時候channel在左邊。意思跟方向是一致的,一個是資料進入channel,一個是資料從channel出去
q := make(chan bool) <-q
有緩衝channel的使用
我們一直使用的無緩衝的channel,今天主要學習下有快取的channel。
func main() { ch := make(chan int) ch<-1 } fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan send]:
有緩衝的channel,可以寫入緩衝大小個資料,可以沒有goroutine從channel讀取。
func main() { ch := make(chan int,2) ch<-1 ch<-2 } Process finished with exit code 0
執行結果跟預期是一致的。
有緩衝大小的channel使用場景
假如我們有一個任務需要10個goroutine去排程執行,只要有一個goroutine執行完畢,排程就應該結束。我們看下虛擬碼
func test(wg *sync.WaitGroup,ch chan int,i int) { fmt.Println("test code") ch<-i } func main() { fmt.Println("start",runtime.NumGoroutine()) ch := make(chan int) wg := new(sync.WaitGroup) for i:=0;i<10;i++ { wg.Add(1) go test(wg,ch,i) } fmt.Println(<-ch) fmt.Println("end",runtime.NumGoroutine()) wg.Done() } start 1 test code 9 end 10
從執行結果上看,是第9個goroutine首先執行完畢了。程式也正常退出了。但是我們看到,加上主goroutine,記憶體中一共有11個goroutine,程式退出的時候還有10個goroutine,減去一個主goroutine,還有9個goroutine沒有退出,這個對程式來說是不允許,可能會洩漏或者長期佔用資源不釋放。
但是我們如果使用了有緩衝的channel,就可以利用channel的緩衝機制正常退出全部的goroutine了。
看下程式碼
func test(wg *sync.WaitGroup,i int) { ch<-i } func main() { fmt.Println("start",runtime.NumGoroutine()) ch := make(chan int,10) wg := new(sync.WaitGroup) for i:=0;i<10;i++ { wg.Add(1) go test(wg,i) } fmt.Println(<-ch,"success") for i:= 0;i<9;i++ { fmt.Println(<-ch) } fmt.Println("end",runtime.NumGoroutine()) wg.Done() } start 1 0 success 1 2 4 3 5 6 7 8 9 end 1 Process finished with exit code 0
列印success的時候,第一個goroutine已經將任務完成,迴圈9次將channel裡面的資料讀取出來,保證建立的goroutine都不會阻塞能夠正常退出來。
到此這篇關於golang開發中channel使用的文章就介紹到這了,更多相關golang channel使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!