简体   繁体   English

在所有 goroutine 完成后让 golang 关闭使用的通道

[英]Let golang close used channel after all goroutines finished

I am trying to run a number of goroutines which will give their results to a channel.我正在尝试运行一些 goroutines,它们会将它们的结果提供给一个通道。 I need a good way to let channel close after all goroutines are done.在所有 goroutine 完成后,我需要一种让通道关闭的好方法。

My first try is to close it after spawn all go routines but I think somehow the channel is closed before all goroutines can send their results.我的第一次尝试是在生成所有 goroutines 后关闭它,但我认为通道在所有 goroutines 发送结果之前以某种方式关闭。

for i:=0; i<=10;i++{
  go func(){
    result:=calculate()
    c<-result
  }()
}
close(c)
for result:= range c{
  all_result=append(all_result, result...)
}

Then, my second try I come up with counting a thread and close it after no thread is running.然后,我第二次尝试计算一个线程并在没有线程运行后关闭它。

for i:=0; i<=10;i++{
  go func(){
    atomic.AddUint64(&go_routine_count, 1)
    result:=calculate()
    c<-result
    atomic.AddUint64(&rt_count, ^uint64(0))
  }()
}
go func(){
  for{
    // some little time to let above goroutine count up go_routine_count before this goroutine can actually check go_routine_count==0
    time.Sleep(time.Millisecond)
    go_current_routine_count:=atomic.LoadUint64(&go_routine_count)
    if go_routine_count==0{
      close(c)
    }
  }
}()
for result:= range c{
  all_result=append(all_result, result...)
}

It works but I feel there might be more correct or more efficient way.它有效,但我觉得可能有更正确或更有效的方法。 Also, somehow in some case if the later goroutine for count check is run before the goroutines in loop, this method won't work.此外,在某些情况下,如果后面的用于计数检查的 goroutine 在循环中的 goroutines 之前运行,则此方法将不起作用。

Is there a better way?有没有更好的办法?

The sync.WaitGroup type should encapsulate what you want to do, without needing sleep calls or busy waiting. sync.WaitGroup类型应该封装您想要做的事情,而不需要睡眠呼叫或忙等待。 It allows you to wait on an arbitrary number of tasks, not worrying about in which order they complete.它允许您等待任意数量的任务,而不用担心它们以什么顺序完成。

Taking your original example, you could alter it to use a wait group like so:以您的原始示例为例,您可以将其更改为使用等待组,如下所示:

    var wg sync.WaitGroup
    for i := 0; i <= 10; i++ {
        wg.Add(1)
        go func(){
            result := calculate()
            c <- result
            wg.Done()
        }()
    }

    // Close the channel when all goroutines are finished
    go func() {
        wg.Wait()
        close(c)
    }()

    for result := range c {
        all_result = append(all_result, result...)
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM