首頁 > 後端開發 > Golang > 主體

可以在Go中同時選擇發送和接收通道而不阻塞嗎?

Susan Sarandon
發布: 2024-10-26 22:34:31
原創
849 人瀏覽過

 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 是否未滿?這模仿了以下功能,但不消耗100% CPU:

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

使用預設情況實現Select

要實現這一點,我們可以利用具有預設情況的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中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!