我正在学习通道如何在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)
}
}
Run Code Online (Sandbox Code Playgroud)
问题是我得到:
致命错误:所有goroutines都睡着了 - 僵局!
当我不关闭频道.究竟是什么导致了僵局?当我不关闭它时,为什么我不能从其容量边界的频道接收到它?
您正在将n个值写入通道(从0到n-1),但是尝试从通道读取n + 1个值(从0到n).如果没有明确关闭通道,main函数将永远等待最后一个值.
究竟是什么导致了僵局?
在n次迭代之后,运行该fibonacci函数的goroutine 将退出.在此goroutine退出之后,程序中唯一剩下的goroutine就是maingoroutine,而这个goroutine正在等待将一些数据写入c通道 - 并且由于没有其他goroutine可能会将数据写入此通道,它将永远等待.这正是错误消息试图告诉你的:"所有goroutines("all"只是"一个",这里)都是睡着了".
该_, ok := <- c呼叫main功能只会停止为尽快阻断c通道被关闭(如从信道阻塞阅读,这需要从另一个goroutine中进行).当通道关闭时,该main功能将从通道读取剩余数据(当它是缓冲通道时)
| 归档时间: |
|
| 查看次数: |
1114 次 |
| 最近记录: |