golang for 循环 + 协程没用?

问题

在写巡检脚本的时候,遇到了如下问题,特此记录。

最开始写的代码如下:

{
    var wg sync.WaitGroup
    for _, a := range activeList {
        wg.Add(1)
    	go func(ia *model.ImportantActivity) {
    		defer wg.Done()
    		if err := GetBusinessData(ia); err != nil {
    			log.Error(err)
    		}
    	}(a)
    	wg.Wait()
    }
}

整个执行下来需要100+ s ,跟没使用协程用了差不多的时间,一点效果没有。

观察自己写的协程好像也没有问题呀,但是什么好像并没有生效呢。

解决

偶然间看到了这段话,突然发现,我这里好像写的是假协程。因为如果把 wg.Add(1) 写在 for 循环里面的话,每次都要等一个for循环结束了,才会创建下一个协程,所以跟没使用协程效果一样。

golang是值拷贝传递。for循环很快,协程创建需要的时间大于for循环的时间。因为协程创建 需要进行 堆栈分配,上下文准备,以及与内核态的线程进行映射工作等。

golang for 循环创建协程问题 https://blog.csdn.net/gu864852213/article/details/119256885

对协程进一步理解后,修改如下:

{
    var wg sync.WaitGroup
    wg.Add(len(activeList))
    for _, a := range activeList {
    	go func(ia *model.ImportantActivity) {
    		defer wg.Done()
    		if err := GetBusinessData(ia); err != nil {
    			log.Error(err)
    		}
    	}(a)
    }
    wg.Wait()
}

整个只执行了 15s。

总结

    • wg.Add 和 wg.Wait 需要写在 for 循环外面,表示开启多少个协程,并等待协程都执行结束
  • 使用 闭包 进行值传递,这样不会产生变量混乱

Go语言协程使用最佳实践 https://zhuanlan.zhihu.com/p/374464199
记一次golang经典错误–for循环中的go协程调用 https://baorongquan.github.io/2018/05/06/%E8%AE%B0%E4%B8%80%E6%AC%A1golang%E7%BB%8F%E5%85%B8%E9%94%99%E8%AF%AF-for%E5%BE%AA%E7%8E%AF%E4%B8%AD%E7%9A%84go%E5%8D%8F%E7%A8%8B%E8%B0%83%E7%94%A8/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值