You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中range遍历channel出现死锁,是否必须在写完数据后关闭channel?

Go Channel死锁问题原因解析

死锁触发原因

Go语言中使用for x := range ch语法遍历channel时,遍历逻辑会持续阻塞等待接收新数据,只有当channel被显式关闭后,遍历循环才会正常退出。
对应你提供的代码场景:

  • 写入goroutine循环往ch1写入10条数据后直接退出,没有关闭channel
  • 读取goroutine遍历完10条数据后,仍然会持续等待ch1的新数据,陷入永久阻塞
  • 主goroutine阻塞在wg.Wait()调用,等待读取goroutine执行wg.Done()回调
    此时所有goroutine都处于阻塞挂起状态,没有可运行的goroutine,Go runtime就会抛出死锁错误。
    当你取消注释关闭channel的代码后,写入goroutine退出前会自动关闭ch1,读取goroutine遍历完所有数据后检测到channel已关闭,就会正常退出循环,执行wg.Done(),主goroutine的等待逻辑也会正常返回,程序顺利结束。

写完数据是否必须手动关闭channel?

不一定,分场景判断:

  • 如果你后续的接收逻辑使用for range遍历channel,或者依赖v, ok := <-ch的ok返回值判断数据是否接收完毕,必须手动关闭channel,否则会出现接收方永久阻塞的问题,甚至触发死锁
  • 如果你的channel生命周期和程序运行周期一致、接收方有其他独立的退出判断逻辑、或者可以保证不会出现接收方无限等待的情况,不需要手动关闭channel。未关闭的channel只要没有外部引用,Go GC会自动回收相关资源,不会出现资源泄漏

另外需要注意:已经关闭的channel不能再写入数据,也不能重复关闭,否则会直接触发panic。

内容的提问来源于stack exchange,提问作者Kade Wu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 01:24:00