亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用異常選擇的意外行為

使用異常選擇的意外行為

Go
Smart貓小萌 2022-07-11 15:58:31
我正在編寫一些代碼,將數據從一個通道傳遞到另一個通道。遵循一些直覺和這個答案,我希望以下代碼能夠工作(other是一個足夠大的緩沖通道并且out是源通道):for {    select {    case other <- (<-out):        log.Warn("C")    }}確實如此!但其他情況根本不會觸發,例如日志中沒有Ds 用于以下代碼:for {    select {    case other <- (<-out):        log.Warn("C")    default:        log.Warn("D")    }}使用更傳統的解決方案,D日志中到處都是 s:for {    select {    case msg := <-out:        other <- msg        log.Warn("C")    default:        log.Warn("D")    }}顯然,我將使用通常的解決方案,但我仍然不知道為什么不尋常的解決方案無法按預期工作。我懷疑答案在Go Memory Model 中的某個地方,但我無法完全弄清楚在這種情況下到底發生了什么。我整理了一些游樂場,您可以在其中查看此行為:Unusal(根本沒有Ds)通常(有很多Ds,您可能必須在本地嘗試才能看到除Ds之外的任何內容)提前感謝任何可以對此有所了解的人!
查看完整描述

1 回答

?
叮當貓咪

TA貢獻1776條經驗 獲得超12個贊

當你有這個:


ch := make(chan int, 10)

// ...


select {

case ch <- <-out:

    fmt.Println("C")

default:

    fmt.Println("D")

}

第一個的通信操作casech <- something,哪里something<-out。但是something首先評估,然后才檢查案例的哪些通信操作可以進行。

所以<-out只要它需要就會阻塞,然后ch <- something檢查它是否可以繼續。由于您使用了足夠大的緩沖區,因此它始終可以在您的示例中繼續進行,因此default永遠不會選擇。

規范:選擇語句:

“select”語句的執行分幾個步驟進行:

  1. 對于語句中的所有情況,在輸入“select”語句時,接收操作的通道操作數以及發送語句的通道和右側表達式僅按源順序計算一次。結果是一組要接收或發送到的通道,以及要發送的相應值。無論選擇哪種(如果有的話)通信操作進行,該評估中的任何副作用都會發生。RecvStmt 左側的帶有短變量聲明或賦值的表達式尚未計算。

  2. 如果一個或多個通信可以進行,則通過統一的偽隨機選擇選擇一個可以進行的通信。否則,如果存在默認情況,則選擇該情況。如果沒有默認情況,“select”語句會阻塞,直到至少有一個通信可以繼續。

  3. 除非所選案例是默認案例,否則執行相應的通信操作。

  4. 如果所選案例是帶有短變量聲明或賦值的 RecvStmt,則計算左側表達式并分配接收到的值(或多個值)。

  5. 執行所選案例的語句列表。

如果你降低 的緩沖區ch,你會看到偶爾在輸出中打印 s(在Go PlaygroundD上試試)。

ch := make(chan int, 2)


查看完整回答
反對 回復 2022-07-11
  • 1 回答
  • 0 關注
  • 149 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號