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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With