【发布时间】:2016-08-09 04:17:41
【问题描述】:
我正在学习通道在 Go 中的工作方式,并且偶然发现了关闭通道的问题。这是 A Tour of Go 中的一个修改示例,它生成 n-1 个斐波那契数并通过通道发送它们,而通道容量的最后一个“元素”未使用。
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n-1; i++ {
c <- x
x, y = y, x+y
}
// close(c) // It's commented out on purpose
}
func main() {
n := 10
c := make(chan int, n)
go fibonacci(n, c)
for i := 0; i < n; i++ {
_, ok := <-c
fmt.Println(ok)
}
}
问题是我得到了:
致命错误:所有 goroutine 都处于休眠状态 - 死锁!
当我不关闭频道时。究竟是什么导致了僵局?不关闭通道,为什么不能在其容量边界内接收?
【问题讨论】:
-
仅供参考,如果您希望关闭频道,读取频道的惯用方式是
for v := range c {,因为您不需要检查 OK - 当频道关闭时,for 循环将退出.如果您不希望频道关闭,请使用for { select { case v := <- c: ...。这样您就可以拥有额外的case条件,例如超时、监控取消令牌等,并在检测到退出条件时打破 for 循环。