Вопрос

I am trying to run a number of goroutines which will give their results to a channel. I need a good way to let channel close after all goroutines are done.

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.

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.

Is there a better way?

Это было полезно?

Решение

The sync.WaitGroup type should encapsulate what you want to do, without needing sleep calls or busy waiting. 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 с атрибуция
Не связан с StackOverflow
scroll top