我一直在努力了解Go中的频道。但有一件事让我很奇怪。你打电话时会发生什么,
For {
select {
case <-chan:
}
}
它是否每次都检查chan以进行更新迭代?如何与普通的case i = int:
或case atomic.LoadUint64() = uint64:
表现进行比较?
答案 0 :(得分:3)
The Go Programming Language Specification
执行“select”语句分几步进行:
- 对于语句中的所有情况,接收操作的通道操作数以及发送的通道和右侧表达式 语句在输入时按源顺序精确评估一次 “选择”声明。结果是一组要接收的通道 from或send to,以及要发送的相应值。任何一方 无论哪个(如果有的话)都会发生评估中的影响 选择通信操作以继续。表达方式 带有短变量声明的RecvStmt的左侧或 作业尚未评估。
- 如果一个或多个通信可以继续,则可以通过统一的伪随机选择来选择可以继续的单个通信。 否则,如果存在默认情况,则选择该情况。如果有 没有默认情况,“select”语句会阻塞至少一个 通讯可以继续。
- 除非所选案例是默认情况,否则将执行相应的通信操作。
- 如果所选案例是具有短变量声明或赋值的RecvStmt,则左侧表达式为 评估并分配收到的值(或值)。
- 执行所选案例的陈述清单。
醇>
select
语句行为在Go Go Programming Language Specification中定义。 <-chan
评估一次。
对于语句中的所有情况,接收的通道操作数 操作以及发送的通道和右侧表达式 语句在输入时按源顺序精确评估一次 “选择”声明。
答案 1 :(得分:1)
通道的实现不是由语言规范定义的(并且永远不会定义),因此特定的实现可以在符合规范的情况下随意执行。< / em>的
另一方面,访问通道的行为类似于访问互斥锁,因此我在内部相信Go安排在适当的资源上使用系统提供的阻止方法。想想Windows上的WaitForMultipleObjects()
,Linux上的futex等等。
换句话说,虽然for { select { case <-chan: ... } }
构造在那些case
标签中的对象上看起来像忙等待,但实际上它不是:编译器利用系统&# 39;当其中一些资源可用时,会通知Go运行时调度程序。