使用Channel 覆蓋Goroutine 中的超時
在Golang 中,當使用Goroutines 和Channel 執行非同步任務時,可以指定超時以確保操作不會無限期地掛起。然而,在某些場景下,超時情況可能不會如預期執行。
考慮以下程式碼片段:
package main import ( "fmt" "time" ) func main() { c1 := make(chan int, 1) // Buffered channel with capacity 1 go func() { for { time.Sleep(1500 * time.Millisecond) // Sleep for 1.5 seconds c1 <- 10 // Send value to channel } }() go func() { for { select { case i := <-c1: fmt.Println(i) case <-time.After(2000 * time.Millisecond): fmt.Println("TIMEOUT") // Not executed } } }() fmt.Scanln() // Wait for user input }
在這段程式碼中,我們有兩個goroutine:一個定期發送一個值傳送到緩衝通道c1,另一個值從c1 中選擇,超時時間為2 秒。但是,超時情況(“TIMEOUT”)永遠不會被列印。
原因在於緩衝通道的性質以及逾時的處理方式。在這種情況下,向 c1 發送值的 goroutine 將每隔 1.5 秒不斷地重新填充通道。因此,第二個 goroutine 中的 select 語句總是會在逾時到期之前從 c1 接收到一個值。
為了解決這個問題並確保逾時情況被執行,我們需要在外部建立超時通道選擇循環。這樣可以防止每次從c1 接收到值時都將其丟棄:
timeout := time.After(2000 * time.Millisecond) // Create timeout channel only once for { select { case i := <-c1: fmt.Println(i) case <-timeout: fmt.Println("TIMEOUT") } }
透過此修改,select 語句將繼續從c1 中選擇,但如果在指定超時內沒有接收到值,則“TIMEOUT”情況將被執行。
以上是如何使用 Go 中的通道可靠地覆蓋 Goroutine 逾時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!