我剛接觸golang。今天測試通道在Golang中的工作方式時,我感到非常困惑。根據教程:僅當緩沖區已滿時才發送到緩沖的通道塊。當緩沖區為空時接收塊。我的測試程序如下所示:package mainimport "fmt"func main() { ch := make(chan int, 2) go func(ch chan int) int { for i := 0; i < 10; i++ { fmt.Println("goroutine: GET ", <-ch) } return 1 }(ch) for j := 0; j < 10; j++ { ch <- j fmt.Println("PUT into channel", j) }}我得到這樣的輸出:PUT into channel 0PUT into channel 1goroutine: GET 0goroutine: GET 1goroutine: GET 2PUT into channel 2PUT into channel 3PUT into channel 4PUT into channel 5goroutine: GET 3goroutine: GET 4goroutine: GET 5goroutine: GET 6PUT into channel 6PUT into channel 7PUT into channel 8PUT into channel 9請注意,編號2是從通道中取出的,甚至沒有放入通道中。為什么會這樣?
1 回答

蝴蝶刀刀
TA貢獻1801條經驗 獲得超8個贊
沒有。將其放在通道上之后Println("PUT into channel")
會發生您的情況,這意味著在執行該print語句之前,有機會從通道中讀取它。
示例輸出中的實際執行順序類似于以下內容:
編寫器例程寫入
2
通道。讀取器例程
2
從通道接收。讀者日常印刷品
goroutine: GET 2
。作家的日常打印
PUT into channel 2
您對通道的讀取和寫入以預期的順序進行,只是您的打印語句使它看起來不正常。
如果您將作者的操作順序更改為:
fmt.Println("PUT into channel", j) ch <- j
您可能會看到輸出更接近您的期望。但是,它不一定完全代表操作順序,因為:
執行是并發的,但對stdout的寫入是同步的
每個函數調用和通道發送/接收都為調度程序提供了切換的機會,因此即使使用進行運行
GOMAXPROCS=1
,它也可以在打印和通道操作(在讀取器或寫入器中)之間切換goroutines。
TL; DR:在記錄并發操作時,不要過多地閱讀日志消息的順序。
- 1 回答
- 0 關注
- 273 瀏覽
添加回答
舉報
0/150
提交
取消