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

Go语言Future模式实现中,为何需将WaitGroup.Wait放入goroutine?

为什么wg.Wait()必须放在goroutine里?

问题的核心在于无缓冲通道的阻塞特性和代码执行顺序的冲突,我们分两种情况拆解:

情况1:同步执行wg.Wait()(移除goroutine)

当你把wg.Wait()放在返回的函数里同步执行时,代码执行流程会彻底卡住:

  1. main里调用future(),进入返回的匿名函数;
  2. 立刻执行wg.Wait(),等待所有checkUrl的goroutine完成;
  3. 但此时checkUrl的goroutine们正在执行c <- urlStatus{...}——由于c是无缓冲通道,发送操作会阻塞直到有接收方读取数据;
  4. 而consumer的goroutine还没开始接收(因为future()还没返回通道c,consumer根本拿不到通道);
  5. 最终形成死锁:checkUrl goroutine阻塞在发送数据,wg.Wait()阻塞在等待这些goroutine结束,main goroutine阻塞在future()的调用上,整个程序彻底停住。

情况2:把wg.Wait()放在goroutine里(正确写法)

这种写法的执行流程是完整闭环的:

  1. main调用future(),进入返回的匿名函数;
  2. 启动一个新goroutine去执行wg.Wait()和关闭通道,当前函数立刻返回通道c;
  3. consumer的goroutine拿到通道c,开始通过range接收数据;
  4. checkUrl的goroutine发送数据时,因为有consumer在接收,不会阻塞,完成后调用wg.Done();
  5. 所有checkUrl完成后,wg.Wait()返回,关闭通道c;
  6. consumer遍历完通道里的所有数据后,发送done信号,main收到后结束程序。

本质原因

无缓冲通道的发送/接收是同步阻塞的,必须同时有发送方和接收方才能完成操作。如果先等待所有发送方完成再给接收方通道,发送方会因为没有接收方而永久阻塞,进而导致等待操作也永久阻塞。把wg.Wait()放到goroutine里,就能让通道先被接收方拿到,保证发送操作能正常完成,最终整个流程顺畅闭环。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:15:36