a <- <- b matches a<- (<-b) , because the <- operator <- associated with the left-most chan possible.
So select has a case with a dispatch (in the form a<- (something) ). And here what happens is that first the right expression of the send operator (the value to be sent) is calculated, which is equal to <-b . But this will be blocked forever (because no one sends anything to b ), therefore:
fatal error: all the mountains are sleeping - a dead end!
The corresponding section forms the Spectrum: Selection Operators:
The execution of the "select" statement is performed in several stages:
For all cases in the instruction, the operands of the channels of the receive operations and the channel and right expressions of the send operators are calculated exactly once in the source order when the "select" operator is entered. The result is a set of channels for receiving or sending and corresponding values ββfor sending. Any side effects in this assessment will occur regardless of which one (if any) for the communication operation. Expressions on the left side of RecvStmt with a short declaration or assignment to a variable have not yet been evaluated.
If one or more messages can continue, one that can continue is selected by uniform pseudo-random selection. Otherwise, if there is a default case, this case is selected. If there is no default case, the "select" statement blocks until at least one of the messages can continue.
...
So, if default present, select does prevent blocking if none of the messages can be executed in step 2 , but your code is stuck in step 1 .
To be complete, if there is a goroutine that sends the value to b , then the evaluation <- b will not be blocked, so the execution of select will not be stuck in step 2, and you will see the expected "select worked as naively expected" (since the reception from a it still cannot continue, so default will be selected):
go func() { b <- 1 }() select { // ... }
Try it on the go playground .
source share