Go チャネルでのタイムアウトの使用
Go では、ゴルーチンとチャネルが強力な同時実行モデルを提供します。ただし、これらのメカニズムを使用する場合は、潜在的な問題を回避するためにタイムアウトを正しく処理することが不可欠です。
チャネルでタイムアウトを使用するときによくある疑問が 1 つあります。それは、なぜタイムアウト ケースが実行されないのかということです。これを調査し、タイムアウトを適切に処理するための解決策を提供してみましょう。
元のコード:
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 が常に到達可能として報告されます。チェック関数が現在のゴルーチンをブロックしているため、タイムアウト ケースは実行されません。
解決策 1: 別のゴルーチンでチェック関数を実行します:
これを解決するには、チェック関数を別のゴルーチンに移動し、別のチャネルを使用して通信します。 result:
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(time.Second): ch <- false } }(url) } return <-ch } func main() { fmt.Println(IsReachable([]string{"url1"})) }
解決策 2: すべての URL に対して単一のタイムアウトを開始する:
または、目的が 1 つの成功したチェックに基づいて到達可能性をレポートすることである場合、すべての URL に対して単一のタイムアウトを使用してタイムアウト処理を簡素化することを検討してください:
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"})) }
Byタイムアウト処理に正しく対処すれば、開発者は Go コードが URL 到達可能性を正確に反映していることを確認でき、より信頼性が高く一貫性のあるアプリケーション エクスペリエンスを提供できます。
以上がGo チャネルの使用時にタイムアウト ケースが実行されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。