golang select语句中case与default的优先级

jon*_*rry 4 go

我有一个运行for循环的多个goroutine应用程序,需要一种方法来指示这些for循环中断,并测试是否发生了超时情况.我正在考虑使用带select语句的共享通道来完成此操作,如下所示:

// 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
  }
}()
Run Code Online (Sandbox Code Playgroud)

这是实现这一目标的有效方法吗?我最关心的select是所选择的分支可能是非确定性的,因此default即使其中一个case已经准备就可以选择.这可能吗?是否有任何文档声明匹配case保证优先于a default.关注的是,done即使发生超时,上面的for循环也可以在关闭后循环几次和/或报告成功.

pet*_*rSO 7

Go编程语言规范

选择陈述

执行"select"语句分几步进行:

  1. 对于语句中的所有情况,接收操作的通道操作数以及发送语句的通道和右侧表达式在输入"select"语句后按源顺序精确计算一次.结果是一组要接收或发送的通道,以及要发送的相应值.无论选择哪种(如果有的话)通信操作进行,评估中的任何副作用都将发生.尚未评估具有短变量声明或赋值的RecvStmt左侧的表达式.
  2. 如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信.否则,如果存在默认情况,则选择该情况.如果没有默认情况,则"select"语句将阻塞,直到至少一个通信可以继续.
  3. 除非所选择的情况是默认情况,否则执行相应的通信操作.
  4. 如果所选案例是具有短变量声明或赋值的RecvStmt,则评估左侧表达式并分配接收值(或多个值).
  5. 执行所选案例的语句列表.

"我最关心的是所选择的选择的分支可能是非确定性的,因此即使其中一个案例已经准备就可以选择默认值.这可能吗?"

不可以.请参阅select规范的第2步.