3 回答
TA贡献1934条经验 获得超2个赞
默认情况下,Go 通道是无缓冲的。这意味着在接收方读取通道之前,它不能在通道上发送。这实际上是 Go 的首选模式。在大多数情况下,它比缓冲通道更有效。
这对您的第一个代码意味着 goroutine 在完成对通道 a 的写入之前无法继续写入通道 b。在主 goroutine 读取 a 之前,它不能这样做。
TA贡献1801条经验 获得超8个赞
默认情况下,通道发送和接收会等待发送例程和接收例程都准备就绪。通过以下示例可以明显看出这种阻塞:
func main() { ch := make(chan int) ch <- 1 fmt.Println(<-ch) }
这段代码会导致死锁,因为唯一的 goroutine(主协程)卡在ch <- 1
,等待另一个 goroutine 接收。它几乎不知道我们期望它成为下一行的接收者。
这解释了为什么您的第一个示例不起作用,因为另一个 goroutineb
在其发送操作a
完成之前不会发送。a
但是主例程在收到之前不会收到b
!所以两者都永远等待着。
TA贡献1772条经验 获得超8个赞
如果您按照顺序执行的方式重写代码,那么发生的事情就会变得更加清晰。
原始代码:
func main() {
a := make(chan bool)
b := make(chan int64)
go func(a chan bool, b chan int64) {
fmt.Println("Here1")
a <- true
b <- 12
} (a,b)
fmt.Println("Here2")
fmt.Println(fmt.Sprintf("%d", <-b))
fmt.Println(fmt.Sprintf("%v", <-a))
}
相同代码顺序执行的紧密表示:
a := make(chan bool)
b := make(chan int64)
fmt.Println("Here2") // Prints
// Pass control to new goroutine
fmt.Println("Here1")
a <- true // Write to channel a and block goroutine here and pass control to main
fmt.Println(fmt.Sprintf("%d", <-b)) // Tries to read from b but nothing has been written to it so blocks. At this point all your goroutines are blocked hence the deadlock.
fmt.Println(fmt.Sprintf("%v", <-a)) // doesn't even reach here.
b <- 12
}
- 3 回答
- 0 关注
- 144 浏览
添加回答
举报