不要通過共享記憶體來通訊,而應該通過通訊來共享記憶體
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...