Go Wait Groups using error Channels
Sat, Dec 10, 2016So you have some task that you can run concurrently, that may return an error. Writing files, making web requests, this sort of thing.
In my previous attempts at go routines, I could not find a way to launching
tasks concurrently and waiting for them to return without using
sync.WaitGroup
. I knew their was a better way with channels.
I have found a pattern I really like, it follows:
func main() {
input := GetInputSlice()
// the errors will be returned through this channel
errChan := make(chan error)
// Range over our input to set off the goroutines
for _, in := range input {
go func(in string) {
// function that only returns an error
errChan <- makeHTTPRequest(in)
}(in)
}
// range over the input again
// this time to make sure all workers return
for _ = range input {
if err := <-errChan; err != nil {
log.Println("Error:", err)
}
}
}
Broken down this looks like:
- Get some kind of input slice
range
over the input, launching go routines, returning onerrChan
range
over input again, receiving onerrChan
I love this as there is no channel passing and there are no counters. When the
second range
over the input is finished, we have been able to receive on
errChan
the same number of times as the number of go routines launched in the
first range. Meaning that every launch of makeHTTPRequest(in)
has returned and
send on errChan
. Now that everyone has returned we can return main and exit.
Look at that, no sync.WaitGroup
or counter here!
See a silly example on the go playground here.