在Go 中使用通道處理超時
問題:
問題:問題:
使用通道檢查URL 清單的可及性,超時條件似乎沒有被執行。這會導致程式碼始終傳回 true,即使某些 URL 無法存取。
分析:package main 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"})) }問題在於 check(u) 函數的實現,其中導致超時永遠不會被執行。在您的程式碼中, check(u) 函數在目前 goroutine 中執行,從而阻止 IsReachable 中 select 語句的執行。當 select 語句被解除阻塞時, check(u) 和 time.After(time.Second) 通道都已準備好被使用,運行時可以選擇其中一個。
解1:
要解決這個問題,你可以在單獨的goroutine 中執行check(u) 函數:package main import "fmt" import "time" func check(u string, ch chan<- bool) { time.Sleep(4 * time.Second) ch <- true } func IsReachable(urls []string) bool { ch := make(chan bool, len(urls)) for _, url := range urls { go check(url, ch) } time.AfterFunc(time.Second, func() { ch <- false }) return <-ch } func main() { fmt.Println(IsReachable([]string{"url1", "url2"})) }在這個修改後的程式碼中, check(u) 函數在goroutine中執行,並將結果傳遞到檢查的通道。 IsReachable 中的 select 語句現在等待已檢查通道或逾時通道準備就緒。這可確保正確處理逾時條件。 解決方案 2:或者,您可以透過為所有 URL 設定單一逾時來簡化程式碼。如果逾時與建立 goroutine 所需的時間相比足夠長,則此方法是可行的:在此程式碼中,使用 time.AfterFunc 為所有 URL 設定單一逾時。如果在逾時期限內可以存取任何 URL,則 ch 通道將收到 true,並且該函數將傳回 true。否則,將向 ch 發送 false,函數將傳回 false。
以上是檢查 URL 可達性時如何正確處理 Go 中通道的逾時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!