Go語(yǔ)言通道之緩沖通道
前文為大家講解了Go語(yǔ)言通道之無(wú)緩沖通道
有緩沖的通道相比于無(wú)緩沖通道,多了一個(gè)緩存的功能,如下圖描述的一樣:
從圖上可以明顯看到和無(wú)緩沖通道的區(qū)別,無(wú)緩沖必須兩個(gè)Goroutine都進(jìn)入通道才能進(jìn)行數(shù)據(jù)的交換,這個(gè)不用,如果數(shù)據(jù)有,直接就能拿走。
package ChannelDemo import ( "fmt" "math/rand" "sync" "time" ) const ( numberGoroutines = 4 taskLoad = 10 ) var bufferWg sync.WaitGroup func init() { rand.Seed(time.Now().Unix()) } func main() { //創(chuàng)建了一個(gè)10任務(wù)的緩沖通道 tasks := make(chan string, taskLoad) bufferWg.Add(numberGoroutines) //創(chuàng)建4個(gè)Goroutine for gr := 1; gr <= numberGoroutines; gr++ { go worker(tasks, gr) } //向緩沖通道中放入數(shù)據(jù) for post := 1; post <= taskLoad; post++ { tasks <- fmt.Sprintf("Task : %d", post) } close(tasks) bufferWg.Wait() } func worker(tasks chan string, worker int) { defer bufferWg.Done() for { task, ok := <-tasks if !ok { fmt.Printf("Worker: %d : 結(jié)束工作 \n", worker) return } fmt.Printf("Worker: %d : 開(kāi)始工作 %s\n", worker, task) //隨機(jī)處理一下工作的時(shí)間 sleep := rand.Int63n(100) time.Sleep(time.Duration(sleep) * time.Millisecond) fmt.Printf("Worker: %d : 完成工作 %s\n", worker, task) } }
運(yùn)行結(jié)果:
Worker: 3 : 開(kāi)始工作 Task : 4
Worker: 2 : 開(kāi)始工作 Task : 2
Worker: 1 : 開(kāi)始工作 Task : 1
Worker: 4 : 開(kāi)始工作 Task : 3
Worker: 4 : 完成工作 Task : 3
Worker: 4 : 開(kāi)始工作 Task : 5
Worker: 2 : 完成工作 Task : 2
Worker: 2 : 開(kāi)始工作 Task : 6
Worker: 3 : 完成工作 Task : 4
Worker: 3 : 開(kāi)始工作 Task : 7
Worker: 1 : 完成工作 Task : 1
Worker: 1 : 開(kāi)始工作 Task : 8
Worker: 3 : 完成工作 Task : 7
Worker: 3 : 開(kāi)始工作 Task : 9
Worker: 1 : 完成工作 Task : 8
Worker: 1 : 開(kāi)始工作 Task : 10
Worker: 4 : 完成工作 Task : 5
Worker: 4 : 結(jié)束工作
Worker: 3 : 完成工作 Task : 9
Worker: 3 : 結(jié)束工作
Worker: 2 : 完成工作 Task : 6
Worker: 2 : 結(jié)束工作
Worker: 1 : 完成工作 Task : 10
Worker: 1 : 結(jié)束工作
因?yàn)槟囊粋€(gè)worker先從通道中取值有系統(tǒng)自己進(jìn)行調(diào)度的,所以每次運(yùn)行的結(jié)果稍微不同,但是相同的是10個(gè)任務(wù)被4個(gè)協(xié)程有條不紊的完成了
注意:main中有一句代碼 Close(tasks) 關(guān)閉通道的代碼非常重要。當(dāng)通道關(guān)閉后,goroutine 依舊可以從通道接收數(shù)據(jù),但是不能再向通道里發(fā)送數(shù)據(jù)。
能夠從已經(jīng)關(guān)閉的通道接收數(shù)據(jù)這一點(diǎn)非常重要,因?yàn)檫@允許通道關(guān)閉后依舊能取出其中緩沖的全部值,而不會(huì)有數(shù)據(jù)丟失.
總結(jié)
無(wú)緩沖的通道保證同時(shí)交換數(shù)據(jù),而有緩沖的通道不做這種保證。
到此這篇關(guān)于Go語(yǔ)言通道之緩沖通道的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
在 Golang 中實(shí)現(xiàn) Cache::remember 方法詳解
這篇文章主要介紹了在 Golang 中實(shí)現(xiàn) Cache::remember 方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03go語(yǔ)言實(shí)現(xiàn)屏幕截圖的示例代碼
屏幕截圖在很多地方都可以 用到,本文主要介紹了go語(yǔ)言實(shí)現(xiàn)屏幕截圖的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Go語(yǔ)言基礎(chǔ)切片的創(chuàng)建及初始化示例詳解
這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)切片的創(chuàng)建及初始化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11go編譯標(biāo)簽build?tag注釋里語(yǔ)法詳解
這篇文章主要為大家介紹了go編譯標(biāo)簽build?tag注釋里語(yǔ)法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Go基礎(chǔ)教程系列之?dāng)?shù)據(jù)類(lèi)型詳細(xì)說(shuō)明
這篇文章主要介紹了Go基礎(chǔ)教程系列之?dāng)?shù)據(jù)類(lèi)型詳細(xì)說(shuō)明,需要的朋友可以參考下2022-04-04再次探討go實(shí)現(xiàn)無(wú)限 buffer 的 channel方法
我們知道go語(yǔ)言?xún)?nèi)置的channel緩沖大小是有上限的,那么我們自己如何實(shí)現(xiàn)一個(gè)無(wú)限 buffer 的 channel呢?今天通過(guò)本文給大家分享go實(shí)現(xiàn)無(wú)限 buffer 的 channel方法,感興趣的朋友一起看看吧2021-06-06Golang利用Template模板動(dòng)態(tài)生成文本
Go語(yǔ)言中的Go?Template是一種用于生成文本輸出的簡(jiǎn)單而強(qiáng)大的模板引擎,它提供了一種靈活的方式來(lái)生成各種格式的文本,下面我們就來(lái)看看具體如何使用Template實(shí)現(xiàn)動(dòng)態(tài)文本生成吧2023-09-09淺析Go常量為什么只支持基本數(shù)據(jù)類(lèi)型
這篇文章主要來(lái)和大家一起討論一下Golang中常量為什么只支持基本數(shù)據(jù)類(lèi)型,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-09-09