チャネルを使用したゴルーチンのタイムアウトのオーバーライド
Golang では、非同期タスクにゴルーチンとチャネルを使用するときに、タイムアウトを指定して次のことを保証できます。操作が無期限にハングすることはありません。ただし、特定のシナリオでは、タイムアウトのケースが期待どおりに実行されない可能性があります。
次のコード スニペットを考えてみましょう:
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 }
このコードには、2 つのゴルーチンがあります。1 つは定期的に送信します。 1 つはバッファリングされたチャネル c1 への値で、もう 1 つは 2 秒のタイムアウトで c1 から選択されます。ただし、タイムアウトの場合 (「TIMEOUT」) は出力されません。
この理由は、バッファリングされたチャネルの性質とタイムアウトの処理方法にあります。このシナリオでは、値を c1 に送信するゴルーチンは、1.5 秒ごとにチャネルを継続的に補充します。その結果、2 番目のゴルーチンの 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 中国語 Web サイトの他の関連記事を参照してください。