【golang】匿名内部协程,值通报与参数通报

打印 上一主题 下一主题

主题 894|帖子 894|积分 2682

代码例子

下面代码的区别是直接调用循环变量,这里使用的就是这个变量的引用,而不是将参数的副本通报给协程执行
  1. for task := range taskChan {
  2.     wg.Add(1)
  3.     go func() {
  4.         defer wg.Done()
  5.         task.Do()  // 使用外部循环变量
  6.     }()
  7. }
复制代码
  1. func DistributeTasks(taskChan <-chan *AddTask, resChan chan int) {
  2.         var wg sync.WaitGroup
  3.         for task := range taskChan {
  4.                 wg.Add(1)
  5.                 go func(t *AddTask) {
  6.                         defer wg.Done()
  7.                         t.Do()
  8.                 }(task) // 注意要当作参数传入,而不是直接在 开启的协程 内部调用task,
  9.         }
  10.         wg.Wait()
  11.         close(resChan)
  12. }
复制代码
结论



  • 大概导致的问题:

    • 在 Go 语言中,当你使用 go 关键字启动一个 goroutine 时,它会在一个新的并发执行单元中运行。在原始代码中,将 task 作为参数通报给匿名函数,确保了每个 goroutine 使用的 task 是独立的,因为函数参数是按值通报的,这意味着在 go 语句执行时,会将 task 的副本通报给匿名函数。
    • 假如不将 task 作为参数通报,而是直接在匿名协程 goroutine 中调用 task,由于 goroutine 大概会在 for 循环的下一次迭代开始后才开始执行,而 for 循环会不绝更新 task 的值,这大概会导致 goroutine 看到的 task 值不是你期望的谁人。
    • 比方:goroutine执行时间很长,而程序中开启goroutine是一个很快的过程,开启完毕之后就执行下一次for循环了,循环变量task也就变了,之前开启的goroutine执行到task.Do() 的时候,已经是其他次循环的task变量

  1. for task := range taskChan {
  2.     wg.Add(1)
  3.     go func() {
  4.         defer wg.Done()
  5.         //假如这里有比较久的耗时操作
  6.         task.Do()  // 使用外部循环变量,这时候可能已经当时那一次循环的task了,因为开启协程这段代码一下子就执行完毕
  7.     }()
  8. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

络腮胡菲菲

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表