Go Channels: タイムアウトが実行されない理由
以下のコード スニペットのようにゴルーチンとチャネルが使用されるシナリオを考えてみましょう。タイムアウト シナリオが決して実現しないのはなぜですか?
func main() { c1 := make(chan int, 1) go func() { for { time.Sleep(1500 * time.Millisecond) c1 <- 10 } }() go func() { for { select { case i := <-c1: fmt.Println(i) case <-time.After(2000 * time.Millisecond): fmt.Println("TIMEOUT") // Not Executed } } }() fmt.Scanln() }
分析
ゴルーチンがおよそ 1.5 秒ごとに c1 チャネルに値を送信し続けるため、タイムアウト シナリオは発生しません。 。タイムアウトは、2 秒間 c1 から値を受信しなかった場合にのみ有効になります。
ただし、c1 から値を受信すると、新しい時間になります。その後の選択実行で呼び出しが行われた後、新しいチャネルが生成されます。ここで、値はさらに 2 秒後にのみ発行されます。前回の選択実行によるタイムアウト チャネルは破棄され、無効になります。
解決策
この問題に対処するには、タイムアウト チャネルを 1 回だけ作成する必要があります。事実上:
timeout := time.After(2000 * time.Millisecond) for { select { case i := <-c1: fmt.Println(i) case <-timeout: fmt.Println("TIMEOUT") // Will be printed after 2 seconds } }
出力
変更されたコードはその後次のように出力されます:
10 TIMEOUT 10 10 10 ...
したがって、タイムアウト シナリオは 2 後に正常に実行されるようになりました。秒、意図した動作を反映します。
以上がGo チャネル: 「select」ステートメントのタイムアウトがトリガーされないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。