{} The Go Reference

Practice · Guide · Reference

Concurrency Cheat-Sheet

A one-page map of Go concurrency — the channel axioms, select idioms, the sync toolbox, the composable patterns, and the gotchas. Built for revision and interview prep.

Practice Reference ⏱ 1 min read Complete

Everything that matters about Go concurrency on one page. Each row links to the full topic; skim to refresh, then dive in.

🎯 The two proverbs

“Don’t communicate by sharing memory; share memory by communicating.” And “concurrency is not parallelism” — concurrency is how you structure independent work; parallelism is it actually running at once. Almost everything below follows from taking those seriously. See Concurrency vs Parallelism.

Channel axioms — what each operation does

Operationnil channelopen, readyopen, not readyclosed
receive <-chblock foreverreturns a valueblockzero value, ok=false, now
send ch <-block foreversendsblockpanic
close close(ch)panicclosesclosespanic

Rules of thumb: the sender owns and closes the channel; closing signals “no more values”; a for range ch drains until close. Buffered channels decouple sender and receiver up to the buffer size. See Channels.

select — pick a ready case

IdiomShape
Timeoutselect { case v := <-ch: …; case <-time.After(d): … }
Non-blockingselect { case v := <-ch: …; default: … }
Cancellationselect { case <-ctx.Done(): return ctx.Err(); case … }
Disable a caseset its channel variable to nil (blocks forever)

A select blocks until one case is ready; if several are, it picks one at random (prevents starvation). See select.

The sync toolbox

ToolUse it for
Mutexexclusive access to shared state
RWMutexmany readers, occasional writer
WaitGroupwait for N goroutines to finish
Onceexactly-once initialization
Condwait/signal on a condition (rare)
Poolreuse short-lived allocations
atomiclock-free counters and flags

Composable patterns

PatternUse it for
Pipelinestream data through channel-connected stages
Fan-out / Fan-inparallelize a stage, then merge results
Worker Poolbound concurrency with N workers
Semaphorecap how many run at once (buffered chan struct{})
Context & Cancellationpropagate cancel, deadline, request values
errgroupconcurrent tasks: wait + first error + cancel
Or-donerange a stream that stops cleanly on cancel
Pub/Subbroadcast to dynamic subscribers

Decision shortcuts — “I need to…”

✅ Channel or mutex, and which tool

  • …transfer ownership of data between goroutineschannel
  • …guard a struct’s internal fieldsMutex
  • …wait for a group to finishWaitGroup
  • …run concurrent tasks that can failerrgroup
  • …cap how many run at onceSemaphore / Worker Pool
  • …cancel a whole tree of goroutinescontext
  • …init exactly oncesync.Once
  • …a fast counter without a lockatomic

Gotchas that bite

⚠️ Keep these in muscle memory

  • Send on a closed channel panics; closing twice panics; receive on closed returns the zero value immediately.
  • A nil channel blocks forever — handy to disable a select case, surprising otherwise.
  • Every goroutine needs an exit — one blocked forever is a leak; give it a done/ctx.
  • WaitGroup.Add before you launch the goroutine, and Done in a defer.
  • A plain map isn’t safe for concurrent writes — guard it or use sync.Map; run the race detector with -race.
  • Don’t copy a Mutex/WaitGroup — pass the struct by pointer.
  • Loop-variable capture in go func(){…} was fixed in Go 1.22; on older versions, pass it as an argument.

Check your understanding

Score: 0 / 3

1. What happens when you send on a closed channel?

Sending on a closed channel panics; so does closing it twice. Receiving from a closed channel is fine — it yields the zero value with ok=false, immediately.

2. You're transferring ownership of data from one goroutine to another. Channel or mutex?

Channels are for transferring ownership and coordinating; mutexes are for guarding a struct's internal state. Pick by intent, not by speed.

3. What does a receive on a nil channel do?

Send and receive on a nil channel both block forever. Setting a channel variable to nil to take its select case out of play is a real, idiomatic technique.

Comments

Sign in with GitHub to join the discussion.