Go Concurrency

Goroutines and sync.WaitGroup

Start lightweight threads with the go keyword and wait for all of them to finish.

  • Advanced
  • 3 min read
  • 1 runnable example
What you'll learn
  • The go keyword
  • WaitGroup: Add, Done, Wait
  • Writing results safely
Five goroutines
  1. 1wg.Add(1)count one more
  2. 2go square(...)runs on its own
  3. 3wg.Done()finished
  4. 4wg.Wait()main continues

Work that runs at the same time

A goroutine is a function that runs at the same time as the rest of the program. Writing go before a call starts one. Goroutines are cheap, so a program can run thousands of them.

main does not wait for goroutines by itself, so a WaitGroup counts them: Add before starting, Done when one finishes and Wait to block until the count is zero. Each goroutine writes to its own position of results, so the output is always the same.

Key points

  1. go f() starts f in a new goroutine.
  2. main does not wait by itself.
  3. wg.Wait blocks until every Done is called.

Runnable Go example

Go
Run code →
main.go
package main

import (
	"fmt"
	"sync"
)

func square(id int, results []int, wg *sync.WaitGroup) {
	defer wg.Done()
	results[id] = id * id
}

func main() {
	var wg sync.WaitGroup
	results := make([]int, 5)

	for id := 0; id < 5; id++ {
		wg.Add(1)
		go square(id, results, &wg)
	}

	wg.Wait() // block until every goroutine calls Done
	fmt.Println(results)
}
Get a Run button for this example Result of running the code
[0 1 4 9 16]

Practice

Open the example in the online compiler, change a value or add a line, and predict the output before you run it. Then break the code on purpose and read the compiler's message.

Finished this lesson?

Mark it as learned to track your progress.

Next: Channels →

Practice with a challenge

Use what this lesson covers to solve a real problem. Each challenge runs in your browser with instant tests and an AI review.

All challenges