为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中关闭通道

在 Go 中关闭通道

Go
手掌心 2022-01-04 15:52:51
我正在学习 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 都处于睡眠状态 - 死锁!当我不关闭频道时。究竟是什么导致了死锁?当我不关闭它时,为什么我不能在其容量边界内从通道接收?
查看完整描述

2 回答

?
千巷猫影

TA贡献1829条经验 获得超7个赞

您正在将n 个值写入通道(从 0 到n-1),但试图从通道中读取n+1 个值(从 0 到n)。如果没有明确关闭通道,main函数将永远等待最后一个值。

究竟是什么导致了死锁?

之后ñ迭代,运行的够程fibonacci功能将退出。在这个 goroutine 退出后,你程序中唯一剩下的 goroutine 就是maingoroutine,这个 goroutine 正在等待一些数据被写入c通道——并且因为没有其他 goroutine 可能会向这个通道写入数据,它会永远等待。这正是错误消息试图告诉您的内容:“所有 goroutines(“all”只是“一个”,这里)都睡着了”

函数中的_, ok := <- c调用main只会在c通道关闭后立即停止阻塞(因为从通道读取是阻塞的,这需要从另一个 goroutine 中完成)。当通道关闭时,该main函数将从通道中读取剩余数据(当它是缓冲通道时)


查看完整回答
反对 回复 2022-01-04
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

主循环中的循环期望在通道中进行 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

}

应该工作 http://play.golang.org/p/zdRuy14f9x


查看完整回答
反对 回复 2022-01-04
  • 2 回答
  • 0 关注
  • 132 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信