Lesson 14 · Concurrency & context

Goroutines

The cheap concurrent function — and the interviewer's favourite distinction.

Your win: launch a goroutine, crisply distinguish concurrency from parallelism, and explain why every goroutine you start needs a way to stop.

A goroutine is a function running concurrently

Prefix a call with go and it runs in a new goroutine, scheduled by the Go runtime — not the OS — onto a small pool of OS threads. Goroutines start with a tiny stack (a few KB) that grows on demand, so you can have hundreds of thousands.1

go handleMessage(msg)   // returns immediately; the work runs concurrently

The launching code does not wait — you need a channel or a WaitGroup (Lessons 15–16) to know when the goroutine is done. Our Kafka engine launches one goroutine per consumer instance and tracks them with a WaitGroup:

internal/golibs/kafka/kafka.go:587-606
k.consumerWaitGroup.Add(1)
go func(member consumer, h MsgHandler) {
    defer func() { k.consumerWaitGroup.Done(); ... }()  // signal completion
    k.runConsumer(spanName, member, h)
}(member, handleMsg)   // args passed in, not captured — see below

Concurrency is not parallelism

The distinction interviewers probe Concurrency is structure: composing independently-executing tasks — dealing with many things at once. Parallelism is execution: literally running things at the same instant on multiple cores. Goroutines give you concurrency; the runtime may run them in parallel across GOMAXPROCS cores, but that's a separate concern.2

Why it matters: you design for concurrency (structure your program as independent pieces that communicate); parallelism is a runtime bonus you mostly don't manage by hand. Our Kafka consumers are structured concurrently — whether two run on two cores in parallel is the scheduler's call.

Every goroutine needs an exit

Goroutine leaks A goroutine that blocks forever (on a channel that never sends, say) never returns — its stack and captured memory are pinned for the life of the process. This is a goroutine leak, the concurrency equivalent of a memory leak. Always give a long-lived goroutine a stop signal — a ctx.Done() or a close channel (Lessons 15, 17).

Our consumers embody this: each runs a loop that selects on its context's Done(), and Close() cancels every consumer context then Wait()s — a clean shutdown, no leaks (the full pattern is Lesson 18).

Anchor — a subtlety you'd get asked about Notice the goroutine takes member/h as parameters rather than capturing loop variables. Before Go 1.22 that was mandatory — a captured loop variable was shared across iterations, a classic bug. Go 1.22 (and our 1.25) made each iteration's variable fresh, so it's fixed — but the repo still passes args explicitly, and interviewers still ask about the old trap.
Watch this next

Rob Pike — "Concurrency is not Parallelism"

The definitive framing, from a Go creator (~30 min). Then do the Tour's concurrency section to launch your first goroutines.

go.dev/blog/waza-talk
A Tour of Go — concurrency

Check yourself (from memory)

Q1. "Concurrency is not parallelism" means…

Concurrency = composing independent tasks (structure); parallelism = running them at once (execution). Go gives the first; the runtime may add the second.

Q2. A goroutine that can never exit causes…

It pins its memory for the process's life — the concurrency memory leak. Give it a ctx.Done()/close-channel exit.

Q3. Compared to an OS thread, a goroutine is…

KB-sized growable stacks, multiplexed by the Go scheduler onto OS threads — so thousands are cheap.
Define concurrency vs parallelism, and say which Go gives you.
recall, then click to reveal
Concurrency = structure: composing independently-executing tasks (dealing with many things at once). Parallelism = execution: running things simultaneously on multiple cores (doing many things at once). Go's goroutines + channels give you concurrency; the runtime scheduler may run them in parallel across GOMAXPROCS cores, but that's separate — you design for concurrency.
Want a peek at how the scheduler (GMP model) multiplexes goroutines onto threads? That's Lesson 23 — but ask me for the short version now.

1. Effective Go — goroutines; A Tour of Go.

2. Rob Pike, Concurrency is not Parallelism.