Go:在通道中使用超時
在Go 中,超時和通道提供了一種方便的方法來控制goroutine 的執行並同步其結果。但是,在某些情況下,超時情況可能不會如預期執行。
問題陳述
考慮以下Go 代碼:
import "fmt" import "time" func check(u string) bool { time.Sleep(4 * time.Second) return true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { select { case ch <- check(u): case <-time.After(time.Second): ch <- false } }(url) } return <-ch } func main() { fmt.Println(IsReachable([]string{"url1"})) }
此程式碼的目標是檢查提供的清單中的所有URL 是否均可訪問。如果任何 URL 在一秒內未能回應,則函數應該會傳回 false。
但是,當執行此程式碼時,它將始終傳回 true。超時情況未執行。
說明
問題是由於 check(u) 的執行方式而產生的。在 IsReachable 函數中,每個 goroutine 透過呼叫 check(u) 檢查 URL 的可及性。然而, check(u) 在返回之前會在當前 goroutine 中休眠 4 秒。
在 select 語句中, case ch
解決方案
要解決此問題,應執行 check(u) 函數在一個單獨的 goroutine 中。這使得 select 語句能夠正確處理逾時情況。
這是更新後的程式碼:
import "fmt" import "time" func check(u string, checked chan<- bool) { time.Sleep(4 * time.Second) checked <- true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { checked := make(chan bool) go check(u, checked) select { case ret := <-checked: ch <- ret case <-time.After(1 * time.Second): ch <- false } }(url) } return <-ch } func main() { fmt.Println(IsReachable([]string{"url1"})) }
現在,如果任何 URL 無法在一秒鐘內回應,函數將傳回錯誤的。此外,如果只有一個 URL 可用,則函數將傳回 true。
以上是為什麼我的 Go 逾時在此通道範例中不起作用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!