Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Let golang close used channel after all goroutines finished

Tags:

go

goroutine

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?

like image 418
A-letubby Avatar asked Feb 17 '14 02:02

A-letubby


People also ask

Do I need to close Golang channel?

It's OK to leave a Go channel open forever and never close it. When the channel is no longer used, it will be garbage collected. Note that it is only necessary to close a channel if the receiver is looking for a close. Closing the channel is a control signal on the channel indicating that no more data follows.

What happens if you close a closed channel Golang?

closing a closed channel will panic, so it is dangerous to close a channel if the closers don't know whether or not the channel is closed. sending values to a closed channel will panic, so it is dangerous to send values to a channel if the senders don't know whether or not the channel is closed.

How do I close a Go channel?

We can close a channel in Golang with the help of the close() function. Once a channel is closed, we can't send data to it, though we can still read data from it. A closed channel denotes a case where we want to show that the work has been done on this channel, and there's no need for it to be open.

How do you wait for Goroutines to finish Golang?

The WaitGroup type of sync package, is used to wait for the program to finish all goroutines launched from the main function. It uses a counter that specifies the number of goroutines, and Wait blocks the execution of the program until the WaitGroup counter is zero.


1 Answers

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 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...)
}
like image 166
James Henstridge Avatar answered Sep 18 '22 13:09

James Henstridge