>> See All Posts
>> See Tech Posts

Go Wait Groups using error Channels

So 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 on errChan
  • range over input again, receiving on errChan

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.