在此示例中,通道已满,因此 select 语句中的第一个 case 将被阻塞,从而导致打印 default case。或者至少那是我认为应该发生的事情。相反,我收到错误消息“所有 goroutine 都处于睡眠状态 - 死锁!”。为什么是这样?我认为 select 语句会阻塞,直到其中一种情况可以运行,这是本示例中的默认情况。
func main() {
c := make(chan int)
c <- 1
select {
case c <- 5:
fmt.Println("a")
default:
fmt.Println("only case not blocked")
// fatal error: all goroutines are asleep - deadlock!
}
}
答案 0 :(得分:2)
执行甚至没有到达 select 语句,因为它在此之前就死锁了。您正在尝试发送到您刚刚创建的频道,但它是无缓冲的 - 无法从中读取任何内容。所以程序死锁,正确地告诉你所有的 goroutines 都被阻塞了。在选择之前删除发送,您将看到预期的行为。
答案 1 :(得分:2)
通道是为 goroutines 通信而设计的。 当一个通道已满时,发送方等待另一个 goroutine 接收它。
无缓冲通道总是满的:必须有另一个 goroutine 来接收发送者发送的内容(同时)。
在这部分中,您写入通道:
c <- 1
这个也写入无缓冲通道,阻塞它:
case c <- 5:
这个例子基于你的代码来展示它是如何工作的:
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go func() {
fmt.Println(<-c) // starting goroutine and continuously reading from chan "c"
}()
time.Sleep(time.Millisecond) //to let goroutine start before program ends
select {
case c <- 5: // write into the channel so goroutine can read
fmt.Println("a")
default:
fmt.Println("only case not blocked")
}
time.Sleep(time.Millisecond) //to let goroutine start before program finishes
}