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

为何需要Goroutine才能使这段Go代码正常运行?代码异常原因咨询

为什么你的Go代码不加go send(c)会阻塞?

这个问题的核心是无缓冲通道的同步阻塞特性和Go代码的执行顺序,咱们一步步拆解来看:

不加go send(c)时的死锁原因

你原代码里创建的是无缓冲通道:c := make(chan int),这种通道的关键规则是:

发送操作c <- val必须等到有接收者准备好接收该值,才能完成;反之,接收操作<-c也必须等到有发送者准备好发送值,才能完成。

当你同步调用send(c)时,执行流程是这样的:

  1. 主goroutine进入send函数,启动10个并发的子goroutine,每个子goroutine要往通道c发送10个值。
  2. 这些子goroutine执行到c <- j时,发现根本没有任何goroutine在接收通道的数据(因为主goroutine还卡在send函数里,receive(c)一行根本没机会执行),于是全部阻塞在发送操作上。
  3. 主goroutine卡在wg.Wait()处,等待这10个子goroutine调用wg.Done(),但子goroutine永远没法完成发送,自然也没法执行wg.Done()——这就形成了死锁:主goroutine等子goroutine,子goroutine等主goroutine提供接收端,互相卡住谁也动不了。

加go send(c)后正常运行的原因

当你把send(c)改成go send(c)时,流程完全变了:

  1. 主goroutine将send函数的执行放到一个新的goroutine中,自己立刻继续执行下一行的receive(c)。
  2. receive函数里的for v := range c会持续从通道c接收数据,这就给send里的子goroutine提供了接收端,它们的c <- j操作终于能正常完成。
  3. 当所有子goroutine都完成10次发送后,send函数里的wg.Wait()结束,随后关闭通道c;receive函数遍历完通道内的所有数据后,因为通道已关闭,循环退出,整个程序正常结束。

总结你的误区

你原本以为send里的wg.Wait()会等内部goroutine完成后再执行receive,但忽略了一个关键前提:send内部的goroutine要完成,必须依赖接收端的存在。同步调用send时,接收端根本没机会启动,导致子goroutine永远阻塞,wg.Wait()永远无法结束,自然到不了receive那一步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:17:31