在 Go 中关闭通道
Closing channels in Go
我正在学习 Go 中的通道如何工作,并且偶然发现了关闭通道的问题。这是 A Tour of Go 的修改示例,它生成 n-1 个斐波那契数并通过通道发送它们,留下最后的 "element" 通道容量未使用。
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)
}
}
问题是我得到:
fatal error: all goroutines are asleep - deadlock!
当我不关闭频道的时候。到底是什么导致了僵局?为什么我不关闭频道却收不到频道的容量边界?
main 中的 For 循环期待通道中的 n 次通信,但你在 func fibonacci 中只产生 n-1
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ { //here
c <- x
x, y = y, x+y
}
// close(c) // It's commented out on purpose
}
您正在将 n 值写入通道(从 0 到 n-1),但正在尝试读取 [=来自通道的 25=]n+1 个值(从 0 到 n)。如果不显式关闭通道,main
函数将永远等待最后一个值。
What exactly is causing the deadlock?
经过n次迭代后,goroutine 运行 fibonacci
函数将退出。在这个 goroutine 退出后,你的程序中唯一剩下的 goroutine 是 main
goroutine,这个 goroutine 正在等待一些数据被写入 c
通道——因为没有其他 goroutine left 可能会将数据写入此通道,它将永远等待。这正是错误消息试图告诉您的内容:"all goroutines ("all" 只是 "one",这里)are asleep".
main
函数中的 _, ok := <- c
调用只会在 c
通道关闭后立即停止阻塞(因为从通道读取是阻塞的,所以需要这样做来自另一个协程)。当通道关闭时,main
函数将从通道中读取剩余数据(当它是缓冲通道时)
我正在学习 Go 中的通道如何工作,并且偶然发现了关闭通道的问题。这是 A Tour of Go 的修改示例,它生成 n-1 个斐波那契数并通过通道发送它们,留下最后的 "element" 通道容量未使用。
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)
}
}
问题是我得到:
fatal error: all goroutines are asleep - deadlock!
当我不关闭频道的时候。到底是什么导致了僵局?为什么我不关闭频道却收不到频道的容量边界?
main 中的 For 循环期待通道中的 n 次通信,但你在 func fibonacci 中只产生 n-1
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ { //here
c <- x
x, y = y, x+y
}
// close(c) // It's commented out on purpose
}
您正在将 n 值写入通道(从 0 到 n-1),但正在尝试读取 [=来自通道的 25=]n+1 个值(从 0 到 n)。如果不显式关闭通道,main
函数将永远等待最后一个值。
What exactly is causing the deadlock?
经过n次迭代后,goroutine 运行 fibonacci
函数将退出。在这个 goroutine 退出后,你的程序中唯一剩下的 goroutine 是 main
goroutine,这个 goroutine 正在等待一些数据被写入 c
通道——因为没有其他 goroutine left 可能会将数据写入此通道,它将永远等待。这正是错误消息试图告诉您的内容:"all goroutines ("all" 只是 "one",这里)are asleep".
main
函数中的 _, ok := <- c
调用只会在 c
通道关闭后立即停止阻塞(因为从通道读取是阻塞的,所以需要这样做来自另一个协程)。当通道关闭时,main
函数将从通道中读取剩余数据(当它是缓冲通道时)