2017-08-09 49 views
1

我有一個運行for循環的多個例程的應用程序,並且需要一種方法來指示這些for循環中斷,並測試是否發生超時情況。我一直在尋找到使用與select語句共享信道來實現這一點,如下所示:golang select語句中的case與default的優先級

// elsewhere in the code, this channel is created, and passed below 
done := make(chan struct{}) 
time.AfterFunc(timeout, func() { close(done) }) 
... 
go func() { 
Loop: 
    for { 
    select { 
    case <-done: 
     break Loop 
    default: 
     foo() 
     time.Sleep(1 * time.Second) 
    } 
    } 
    select { 
    case <-done: 
    panic("timed out!") 
    default: 
    // ok 
    } 
}() 

這是做到這一點的有效方法?我最關心的是選擇的select的分支可能是非確定性的,因此即使case中的一個準備就緒,也可以選擇default。這可能嗎?是否有任何文件表明匹配的case保證優先於default。值得關注的是,在done關閉和/或報告成功後,即使發生超時,上面的for循環可能會循環多次。

回答

6

The Go Programming Language Specification

Select statements

在幾個步驟的「選擇」的聲明收益的執行:

  1. 對於在聲明中所有的情況下,渠道操作數接收操作和發送 語句的通道和右側表達式按照源順序精確評估一次,一旦輸入 「select」 tatement。結果是一組接收 或從中發送的通道,以及要發送的相應值。無論哪個(如果有的話) 通信操作被選擇繼續進行,將發生該評估中的任何一方的效果。尚未評估具有短變量聲明或 賦值的RecvStmt左邊的 表達式。
  2. 如果一個或多個通信可以繼續進行,可以進行的單個通過一個統一的僞隨機選擇。 否則,如果存在默認情況,則選擇該情況。如果 不是默認情況,則「選擇」語句會阻塞,直到至少有一個通信可以繼續進行。
  3. 除非所選情況是默認情況,否則將執行相應的通信操作。
  4. 如果選擇的案例是帶有短變量聲明或賦值的RecvStmt,則會對左側表達式進行求值並分配接收的值(或多個值) 。
  5. 執行所選案例的語句列表。

「我最關心的是,一個選擇是 選擇可能是不確定性,使默認可以選擇甚至 如果的一個分支案件已經準備好了,這可能嗎?「

否參見select規範的第2步。

+0

這也包括在內(不詳細)[在圍棋遊覽](https://tour.golang.org/concurrency/6)。 – Adrian