Learn Go← Dashboard

Lightweight concurrent functions started with the go keyword.

The go Keyword

A goroutine is a function running concurrently with the rest of your program. You start one by prefixing a function call with go.

go work()

That's it. The runtime takes care of scheduling thousands of goroutines onto a handful of OS threads. Goroutines are tiny — a few kilobytes each — so you can have millions at once.

A first goroutine

go playground
Loading...

The two say calls run side by side. The output is interleaved.

The big "but" — main doesn't wait

If main returns, the whole program ends, even if other goroutines are still running. You usually need a way to wait for the goroutines you started:

  • a channel — preferred, you'll see it in the next chapter,
  • a sync.WaitGroup,
  • or just time.Sleep for demos.
go playground
Loading...

Run that — most likely nothing prints. Now run this:

go playground
Loading...

WaitGroup is a small counter — Add(n) increases it, Done() decreases it, Wait() blocks until it reaches zero.

Concurrency vs parallelism

Goroutines are concurrent — they're logically independent. Whether they run in parallel depends on how many CPU cores Go uses (which you can read and set via runtime.NumCPU() and GOMAXPROCS, but the default is "all cores", which is what you want).

Don't communicate by sharing memory; share memory by communicating.

— A Go proverb. The "communicating" bit is channels, the next chapter.

Goroutine leaks

A goroutine that blocks forever (waiting on a channel that nobody sends to, a mutex never released, a network read that never returns) stays alive until the program exits. The garbage collector cannot free it because it's still "running". This is called a leak and it's the most common concurrency bug in Go.

Always make sure every goroutine you start has a path to finish. The two common tools are:

  • context.Context — pass a cancellation signal in, return when it fires.
  • Closing channelsrange over a channel exits when the channel is closed.

We cover both later in this track.

What happens if `main()` returns while other goroutines are still running?