ホームページ  >  記事  >  バックエンド開発  >  Go で送信チャネルと受信チャネルの両方をブロックせずに選択できますか?

Go で送信チャネルと受信チャネルの両方をブロックせずに選択できますか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-26 22:34:31836ブラウズ

 Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

条件付き送信および受信用の双方向チャネルの選択

Go では、送信と受信の両方にバッファリングされたチャネルを設定して、可用性に基づいて選択的な操作を実行します。次のシナリオを考えてみましょう:

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

バッファリングされた送信チャネル s とバッファリングされていない受信チャネル r があります。疑問が生じます: r にデータがあるか、s がいっぱいではないかを判断するために両方のチャネルを選択できるでしょうか?これは次の機能を模倣しますが、CPU を 100% 消費することはありません:

<code class="go">for {
    if len(s) < cap(s) {
        // Send something
    }
    if len(r) > 0 {
        // Receive something
    }
}</code>

デフォルト ケースを使用した選択の実装

これを実現するには、デフォルトのケースを使用した select ステートメント。デフォルトの場合、どちらのチャネルも準備ができていない場合は、不要なリソースの消費を避けるために goroutine を一時的に「スリープ」させます。

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

for {
    v := valueToSend() // Value to be sent, evaluated upon each attempt
    select {
    case s <- v:
        fmt.Println("Sent value:", v)
    case vr := <-r:
        fmt.Println("Received:", vr)
    default: // Neither channel is ready, pause briefly
        time.Sleep(time.Millisecond * 1)
    }
}

長さと容量のチェックが理想的ではない理由

送信または受信を試みる前に、チャネルの長さや容量を確認しないようにすることが重要です。これは、チェック時と実際の操作の間でチャネルの状態が変化する可能性があり、予期しないブロックが発生する可能性があるためです。例:

<code class="go">if len(r) > 0 {
    // r is ready to receive

    // Other code...

    r <-  // This may block if another goroutine has already received from r!
}</code>

以上がGo で送信チャネルと受信チャネルの両方をブロックせずに選択できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。