我正在尝试运行许多goroutine,这些例程会将其结果提供给某个渠道。我需要一种好的方法来在所有goroutine完成后让通道关闭。
我的第一个尝试是在产生所有go例程之后关闭它,但是我认为以某种方式在所有goroutine可以发送结果之前关闭通道。
for i:=0; i<=10;i++{ go func(){ result:=calculate() c<-result }() } close(c) for result:= range c{ all_result=append(all_result, result...) }
然后,我第二次尝试计算一个线程,并在没有线程运行后将其关闭。
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...) }
它可行,但我认为可能有更正确或更有效的方法。同样,在某种情况下,如果稍后的计数检查goroutine在goroutines循环之前运行,则此方法将不起作用。
有没有更好的办法?
该sync.WaitGroup类型应封装您要执行的操作,而无需睡眠呼叫或忙于等待。它使您可以等待任意数量的任务,而不必担心它们完成的顺序。
sync.WaitGroup
以您的原始示例为例,您可以将其更改为使用等待组,如下所示:
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...) }