golang開發(fā)中channel使用
channel[通道]是golang的一種重要特性,正是因為channel的存在才使得golang不同于其它語言。channel使得并發(fā)編程變得簡單容易有趣。
channel的概念和語法
一個channel可以理解為一個先進(jìn)先出的消息隊列。channel用來在協(xié)程[goroutine]之前傳遞數(shù)據(jù),準(zhǔn)確的說,是用來傳遞數(shù)據(jù)的所有權(quán)。一個設(shè)計良好的程序應(yīng)該確保同一時刻channel里面的數(shù)據(jù)只會被同一個協(xié)程擁有,這樣就可以避免并發(fā)帶來的數(shù)據(jù)不安全問題[data races]。
正文
channel主要是用于多個goroutine之間通信
channel語法
channel是引用類型,需要實用make來創(chuàng)建channel,如下
make(chan Type, [buffer])
chan Type 通道的類型
buffer 是可選參數(shù),代表通道緩沖區(qū)的大小(省略則代表無緩沖)
向channel里面寫入數(shù)據(jù)使用 <- 符號
q := make(chan bool) q<-true
從channel里面讀取數(shù)據(jù)也是使用 <- 符號,只不過寫入的channel在右邊,讀取的時候channel在左邊。意思跟方向是一致的,一個是數(shù)據(jù)進(jìn)入channel,一個是數(shù)據(jù)從channel出去
q := make(chan bool) <-q
有緩沖channel的使用
我們一直使用的無緩沖的channel,今天主要學(xué)習(xí)下有緩存的channel。
無緩沖的channel,寫入數(shù)據(jù)后一定要有g(shù)oroutine 從channel讀取數(shù)據(jù)后再寫入,否則程序會panic。
func main() { ch := make(chan int) ch<-1 } fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan send]:
有緩沖的channel,可以寫入緩沖大小個數(shù)據(jù),可以沒有g(shù)oroutine從channel讀取。
func main() { ch := make(chan int,2) ch<-1 ch<-2 } Process finished with exit code 0
執(zhí)行結(jié)果跟預(yù)期是一致的。
有緩沖大小的channel使用場景
假如我們有一個任務(wù)需要10個goroutine去調(diào)度執(zhí)行,只要有一個goroutine執(zhí)行完畢,調(diào)度就應(yīng)該結(jié)束。我們看下偽代碼
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
從執(zhí)行結(jié)果上看,是第9個goroutine首先執(zhí)行完畢了。程序也正常退出了。但是我們看到,加上主goroutine,內(nèi)存中一共有11個goroutine,程序退出的時候還有10個goroutine,減去一個主goroutine,還有9個goroutine沒有退出,這個對程序來說是不允許,可能會泄漏或者長期占用資源不釋放。
但是我們?nèi)绻褂昧擞芯彌_的channel,就可以利用channel的緩沖機制正常退出全部的goroutine了。
看下代碼
func test(wg *sync.WaitGroup,ch chan int,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,ch,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已經(jīng)將任務(wù)完成,循環(huán)9次將channel里面的數(shù)據(jù)讀取出來,保證創(chuàng)建的goroutine都不會阻塞能夠正常退出來。
到此這篇關(guān)于golang開發(fā)中channel使用的文章就介紹到這了,更多相關(guān)golang channel使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go實現(xiàn)grpc四種數(shù)據(jù)流模式
這篇文章主要為大家介紹了go實現(xiàn)grpc四種數(shù)據(jù)流模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04詳解Go是如何優(yōu)雅的進(jìn)行內(nèi)存管理
Go語言拋棄C/C++中的開發(fā)者管理內(nèi)存的方式,實現(xiàn)了主動申請與主動釋放管理,增加了逃逸分析和垃圾回收,將開發(fā)者從內(nèi)存管理中釋放出來,作為進(jìn)階的Go開發(fā),了解掌握Go的內(nèi)存管理還是很有必要的2023-09-09Golang在Window環(huán)境使用Imagick7的過程
這篇文章主要介紹了Golang在Window環(huán)境使用Imagick7的過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-11-11Golang 數(shù)據(jù)庫操作(sqlx)和不定字段結(jié)果查詢
本文主要介紹了Golang 數(shù)據(jù)庫操作(sqlx)和不定字段結(jié)果查詢,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09