2017-08-09 384 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