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
上面的代码导致fatal error: all goroutines are sleep - deadlock!
。
但是如果我改变一行:
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)
}
}
效果不错。
为什么第一个版本的代码会导致死锁,为什么这个改变能让代码工作?
最佳答案
按照标准 select statement包含一堆 Send或 Receive声明。
在本例中是发送语句。
发送语句定义为:
SendStmt = Channel "<-" Expression .
Channel = Expression .
查看您的代码:
case c <- <-chan_never_used:
Channel
分数是 c
, Expression
分数是 <-chan_never_used
.
因此,select
发送语句(可能)非阻塞的语义不适用,因为它是阻塞的表达式。在应用 Send Statements 语义之前,必须完全评估 Expression 部分。
关于go - 按时选择。结果死锁后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43303406/