package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case c <- <-chan_never_used:
}
println(<-c)
}
}
https://play.golang.org/p/7hZMdITecg
The code above results in fatal error: all goroutines are asleep - deadlock!
.
But if I change one line:
package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case n := <-chan_never_used: // This line changed
c <- n // Add this line
}
println(<-c)
}
}
It works well.
Why the first version of code results in deadlock and why could this change make the code work?
As per the standard the select statement contains of a bunch of Send or Receive statements.
In this case it is the send statement.
Send statement is defined as:
SendStmt = Channel "<-" Expression .
Channel = Expression .
Looking at your code:
case c <- <-chan_never_used:
The Channel
fraction is c
, the Expression
fraction is <-chan_never_used
.
So, the select
semantics of the Send Statement of being (potentially) non-blocking is not applicable because it is the expression that blocks. And before the Send Statements semantics is applied the Expression part must be completely evaluated.