我有一个运行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
}
}()
这是实现此目的的有效方法吗?我最关心的是所选择的select
的分支可能是非确定性的,因此即使其中一个default
s,也可以选择case
准备好了。这可能吗?是否有任何文档表明匹配的case
保证优先于default
。关注的是上面的for循环可能会在done
关闭后循环多次和/或报告成功,即使发生了超时。
答案 0 :(得分:7)
The Go Programming Language Specification
执行“select”语句分几步进行:
- 对于语句中的所有情况,接收操作的通道操作数以及发送的通道和右侧表达式 语句在输入时按源顺序精确评估一次 “选择”声明。结果是一组要接收的通道 from或send to,以及要发送的相应值。任何一方 无论哪个(如果有的话)都会发生评估中的影响 选择通信操作以继续。表达方式 带有短变量声明的RecvStmt的左侧或 作业尚未评估。
- 如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信。 否则,如果存在默认情况,则选择该情况。如果有 没有默认情况,“select”语句会阻塞至少一个 通讯可以继续。
- 除非所选案例是默认情况,否则将执行相应的通信操作。
- 如果所选案例是具有短变量声明或赋值的RecvStmt,则左侧表达式为 评估并分配收到的值(或值)。
- 执行所选案例的陈述清单。
醇>
“我最关心的是选择的分支 选择可能是非确定性的,因此可以选择默认值 如果其中一个案件准备就绪这可能吗?“
没有。请参阅select
规范的第2步。