我正在尝试运行一些goroutines,它们会将结果发送到一个频道.在完成所有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
类型应该封装您想要做的事情,而不需要睡眠呼叫或忙碌等待.它允许您等待任意数量的任务,而不必担心它们完成的顺序.
以您的原始示例为例,您可以将其更改为使用等待组:
- 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...)
- }