ホームページ > バックエンド開発 > Golang > Go チャネル: 「select」ステートメントのタイムアウトがトリガーされないのはなぜですか?

Go チャネル: 「select」ステートメントのタイムアウトがトリガーされないのはなぜですか?

DDD
リリース: 2024-12-26 03:37:09
オリジナル
409 人が閲覧しました

Go Channels: Why Doesn't My Timeout in a `select` Statement Ever Trigger?

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート