GO語言實戰十 管道

2021-10-01 23:45:47 字數 3759 閱讀 2358

不要通過共享記憶體來通訊,而應該通過通訊來共享記憶體

channel 也是go語言裡的一種引用型別,通道可以被認為是goroutines通訊的管道。類似於管道中的水從一端到另一端的流動,資料可以從一端傳送到另一端,通過通道接收。

當乙個資源需要在 goroutine 之間共享時,通道在 goroutine 之間架起了乙個管道,並提供了 確保同步交換資料的機制。宣告通道時,需要指定將要被共享的資料的型別。可以通過通道共享 內建型別、命名型別、結構型別和引用型別的值或者指標。

無緩衝的通道保證同時交換資料,而有緩衝的通道不做這種保證

//建立 無緩衝通道 整型

unbuffer :=

make

(chan

int)

//建立 有緩衝通道 字串型

buffer :=

make

(chan

string,10

) fmt.

printf

("%t*****%t"

,unbuffer,buffer)

//chan int*****chan string通道收到了 test1

buffer

"test1"

//從通道接收字串

value :=

fmt.

println

("通道收到了"

,value)

//通道收到了 test1

無緩衝的通道(unbuffered channel)是指在接收前沒有能力儲存任何值的通道。這種型別的通 道要求傳送 goroutine 和接收 goroutine 同時準備好,才能完成傳送和接收操作。如果兩個 goroutine 沒有同時準備好,通道會導致先執行傳送或接收操作的 goroutine 阻塞等待。這種對通道進行傳送 和接收的互動行為本身就是同步的。其中任意乙個操作都無法離開另乙個操作單獨存在。

兩個 goroutine 都到達通道,但哪個都沒有開始執行傳送或者接收。

左側 的 goroutine 將它的手伸進了通道,這模擬了向通道傳送資料的行為。這時,這個 goroutine 會在 通道中被鎖住,直到交換完成。

右側的 goroutine 將它的手放入通道,這模擬了從通 道裡接收資料。這個 goroutine 一樣也會在通道中被鎖住,直到交換完成。

在第 4 步和第 5 步, 進行交換,並最終,

在第 6 步,兩個 goroutine 都將它們的手從通道裡拿出來,這模擬了被鎖住 的 goroutine 得到釋放。兩個 goroutine 現在都可以去做別的事情了。

func

unbuffertest()

//模擬選手打球

func

play

(name string

, court chan

int)

n := rand.

intn

(100

)if n%5==

0 fmt.

printf

("選手 %s 打出了第%d次球\n"

,name,ball)

ball++

//打球給對方

court

輸出選手 李四 打出了第1次球

選手 張三 打出了第2次球

missied 李四

winner is 張三

有緩衝的通道(buffered channel)是一種在被接收前能儲存乙個或者多個值的通道。這種類 型的通道並不強制要求 goroutine 之間必須同時完成傳送和接收。通道會阻塞傳送和接收動作的 條件也會不同。只有在通道中沒有要接收的值時,接收動作才會阻塞。只有在通道沒有可用緩衝 區容納被傳送的值時,傳送動作才會阻塞。這導致有緩衝的通道和無緩衝的通道之間的乙個很大 的不同:無緩衝的通道保證進行傳送和接收的 goroutine 會在同一時間進行資料交換;有緩衝的 通道沒有這種保證。

* 有緩衝通道

*/var wg sync.waitgroup

const

(//開啟的goroutine數量

numbergoroutine =

4//要處理的工作的數量

taskload =10)

func

init()

func

main()

func

buffertest()

addwork

(tasks)

close

(tasks)

wg.wait()

}//增加工作

func

addwork

(tasks chan

string)}

//模擬選手打球

func

work

(tasks chan

string

, worker int

)//開始同坐

fmt.

printf

("工人%d開始幹活了,幹的是%s\n"

, worker, task)

//模擬工作時間 等待時間

sleep := rand.

int63n

(100

) time.

sleep

(time.

duration

(sleep)

* time.millisecond)

//完成工作

fmt.

printf

("工人%d 完成了工作任務《%s》>\n"

, worker, task)}}

輸出:工人4開始幹活了,幹的是工作任務1

工人2開始幹活了,幹的是工作任務2

工人3開始幹活了,幹的是工作任務3

工人1開始幹活了,幹的是工作任務4

工人4 完成了工作任務《工作任務1》>

工人4開始幹活了,幹的是工作任務5

工人4 完成了工作任務《工作任務5》>

工人4開始幹活了,幹的是工作任務6

工人1 完成了工作任務《工作任務4》>

工人1開始幹活了,幹的是工作任務7

工人2 完成了工作任務《工作任務2》>

工人2開始幹活了,幹的是工作任務8

工人1 完成了工作任務《工作任務7》>

工人1開始幹活了,幹的是工作任務9

工人4 完成了工作任務《工作任務6》>

工人4開始幹活了,幹的是工作任務10

工人2 完成了工作任務《工作任務8》>

工作結束了

工人1 完成了工作任務《工作任務9》>

工作結束了

工人3 完成了工作任務《工作任務3》>

工作結束了

工人4 完成了工作任務《工作任務10》>

工作結束了

第 46 行中關閉通道的**非常重要。當通道關閉後,goroutine 依舊可以從通道接收資料, 但是不能再向通道

裡傳送資料

讀《Go 語言實戰》

英文版書名 go in action william kennedy brian ketelsen eirk st.martin 著2017年3月 第 1 版 go 語言是現代的,快速的,帶有乙個強大的標準庫。內建對併發的支援 使用介面作為 復用的基礎模組。一,go語言介紹 二,快速開始乙個go程式...

go語言實戰 摘抄

測試 func foo list int return func main foo list fmt.printf v list 結果 10,11,12 在64位架構的機器上,乙個切片需要24位元組的記憶體,指標字段需要8位元組,長度和容量各需要8位元組。指向t型別的值的方法集只包含值接收者宣告的方...

go語言實戰筆記 二

碼 之前一定要安裝go,哈哈哈哈,反正我只裝goland然後寫不了 報錯,卡在第一段 哈哈哈哈哈哈 新建專案goproject 新建src資料夾 新建main資料夾 新建第乙個go檔案 開始寫 好了,我用一秒鐘的時間寫完了下面的 package main import bufio fmt os my...