How to: Handle Errors within Wait Groups

· 238 words · 2 minutes read

One of the many benefits of using Go is it's simplicity when it comes to concurrency. With WaitGroups being an excellent example of this. It can be tricky though to handle both concurrency and errors effectively. This post aims to outline how you can run multiple goroutines and handle any errors effectively, without stopping program execution.

The essence of this comes down to these three key parts:

  • Creating two channels, for passing errors and when the WaitGroup is complete.
  • A final goroutine to listen for the WaitGroup to complete, closing a channel when that happens.
  • A select listening for errors or the WaitGroup to complete, whichever occurs first.
package main

import (

func main() {

	// Make channels to pass fatal errors in WaitGroup
	fatalErrors := make(chan error)
	wgDone := make(chan bool)

	var wg sync.WaitGroup

	go func() {
		log.Println("Waitgroup 1")
		// Do Something...
	go func() {
		log.Println("Waitgroup 2")
		// Example function which returns an error
		err := ReturnsError()
		if err != nil {
			fatalErrors <- err

	// Important final goroutine to wait until WaitGroup is done
	go func() {

	// Wait until either WaitGroup is done or an error is received through the channel
	select {
	case <-wgDone:
		// carry on
	case err := <-fatalErrors:
		log.Fatal("Error: ", err)

	log.Println("Program executed successfully")

func ReturnsError() error {
	return errors.New("Example error on")

handling errors in wait groups

Image of Author Edd Turtle

Author:  Edd Turtle

Edd is the Lead Developer at Hoowla, a prop-tech startup, where he spends much of his time working on production-ready Go and PHP code. He loves coding, but also enjoys cycling and camping in his spare time.

See something which isn't right? You can contribute to this page on GitHub or just let us know in the comments below - Thanks for reading!