a <- <- b
与a<- (<-b)
相同,因为<-
运营商与最左边的chan
可能关联。
所以select
有一个case
与发送操作(的形式a<- (something)
)。这里发生的是send语句的右侧表达式(要发送的值)首先被计算 - 这是<-b
。但是,这将永远阻止(因为没有人在b
发送任何数据),所以:
fatal error: all goroutines are asleep - deadlock!
相关部分形成Spec: Select statements:
Execution of a "select" statement proceeds in several steps:
For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the "select" statement. The result is a set of channels to receive from or send to, and the corresponding values to send. Any side effects in that evaluation will occur irrespective of which (if any) communication operation is selected to proceed. Expressions on the left-hand side of a RecvStmt with a short variable declaration or assignment are not yet evaluated.
If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.
...
所以,如果default
存在,则select
确实防止阻塞,如果没有的通信可以在步骤2中继续,但是您的代码卡在步骤1中。
只要是完整的,是否会有这将在b
发送的值,那么<- b
评价不会阻止的goroutine,所以select
的执行将不会停留在步骤2中,和你会看到预期的"select worked as naively expected"
(因为从a
接收仍然无法因此继续default
将选择):
go func() { b <- 1 }()
select {
// ...
}
尝试它的Go Playground。