php小編柚子在這篇文章中會回答一個常見問題:「為什麼Go Channel的緩衝區無法正確限制寫入/讀取?」在Go語言中,Channel是一種用於協程之間通訊的機制。當我們使用具有緩衝區的Channel時,期望能夠透過限制寫入或讀取操作的數量來控製程式的行為。然而,實際上,Channel的緩衝區並不能直接限制寫入/讀取操作的數量。以下將詳細闡述這個問題的原因和解決方案。
我正在嘗試使用通道在兩個 go 例程之間進行通訊。首先,我創建了整數通道,然後將其作為參數傳遞給 go 例程,該例程列印從 0 到 10 的數字序列。這些程式的輸出沒有意義。
這是主要程式碼:
func worker(identifier string, ch chan<- int) { fmt.printf("entering worker %s\n", identifier) for i := 0; i < 10; i++ { fmt.printf("writing %d\n", i) ch <- i } fmt.printf("exiting worker %s\n", identifier) close(ch) } func main() { ch := make(chan int) go worker("1", ch) for v := range ch { fmt.printf("reading %d\n", v) } }
對於該程式碼執行,我得到了以下輸出:
entering worker 1 writing 0 writing 1 reading 0 reading 1 writing 2 writing 3 reading 2 reading 3 writing 4 writing 5 reading 4 reading 5 writing 6 writing 7 reading 6 reading 7 writing 8 writing 9 reading 8 reading 9 exiting worker 1
請注意,有兩個寫入執行,然後是兩次讀取執行。
後來,我設定了一個緩衝區大小來實現以下功能:
func main() { ch := make(chan int, 3) // <= buffer go worker("1", ch) for v := range ch { fmt.printf("reading %d\n", v) } }
然後,得到以下輸出:
Entering worker 1 Writing 0 Writing 1 Writing 2 Writing 3 Writing 4 Reading 0 Reading 1 Reading 2 Reading 3 Reading 4 Writing 5 Writing 6 Writing 7 Writing 8 Writing 9 Reading 5 Reading 6 Reading 7 Reading 8 Reading 9 Exiting worker 1
請注意,現在我們有 5 個寫入執行,然後有 5 個讀取執行。
一旦我們有了程式碼和輸出,最後一個問題就來了:為什麼這些執行的行為是這樣的?首先,它不是應該每次只讀取和寫入一個數字嗎?除此之外,為什麼第二次執行每次讀取和寫入 5 個數字而不是 3 個(因為這是緩衝區大小)?
當列印訊息時以及何時從通道讀取或寫入數字時,您會混淆。
當寫入發生時,不會發生「寫入」訊息。它們發生在寫入之間的某個時刻。同樣,「正在閱讀」訊息發生在讀取之間的某個時刻。
這是安排第一個程式碼片段的一種方法,它會產生顯示的輸出:
Control 像這樣在 main 和 Worker 之間不斷傳遞,每個在阻塞之前列印 2 個訊息。
同樣,您的第二個片段也可以這樣安排:
以上是為什麼Go Channel的緩衝區不能正確限制寫入/讀取?的詳細內容。更多資訊請關注PHP中文網其他相關文章!