Go ConcurrencyFrom Fundamentals to Production
Twenty-two chapters, from the mental models through goroutines, channels and select, to shared state and the memory model, context and cancellation, and the production discipline of testing, debugging and performance, down to the scheduler itself. Every figure is measured on a named machine, and every chapter ends in an exercise whose test fails until you make it pass.
Seven lanes. Twenty-two runs. Read left to right.
Each part is a lane, like a processor in go tool trace.
Each chapter is a span scheduled onto its lane, and its width is its
length in prose. Hover a span to read the chapter; the list below is
the same data in reading order.
P0 foundations3 h
- 01Understanding ConcurrencyConcurrency vs parallelism, CSP and share-memory-by-communicating, I/O-bound vs CPU-bound work, goroutines vs OS threads, and GOMAXPROCS on Go 1.25+ — the mental models the rest of the book builds on.0.6 h
- 02GoroutinesCreating goroutines with go, why main returning kills them all, coordinating with sync.WaitGroup and wg.Go, the six ways goroutines leak, and what they actually cost — measured, not guessed.0.9 h
- 03ChannelsChannels as rendezvous points, not pipes: send and receive blocking semantics, the comma-ok idiom and zero-value ambiguity, the sender-closes principle, for range over channels, and why nil channels block forever.0.8 h
- 04SelectThe select statement: how it evaluates and picks uniformly at random among ready cases, non-blocking work with default and the spin loop it invites, timeouts after Go 1.23 rewrote timers, priority patterns, and nil channels as dynamic case control.1.1 h
P1 channel mastery2 h
- 05Buffered ChannelsBuffered channels: what capacity changes about blocking, the N-1 rule for sizing against goroutine leaks, when a buffer helps and the four anti-patterns where it only delays failure, and buffered channels as counting semaphores.0.7 h
- 06Directional Channels and API DesignDirectional channel types: what chan<- T and <-chan T let the compiler enforce, where capability ends and convention begins, the five ownership patterns, and how narrowing a channel at a function boundary turns sender-closes into a rule the compiler keeps.0.7 h
- 07Channel PatternsThe six channel patterns production Go is built from: pipelines that propagate closure and cancellation, fan-out/fan-in, worker pools with graceful shutdown, or-channel and or-done, and tee/broadcast — each with the failure it exists to prevent.0.9 h
P2 shared state6 h
- 08Data Races and the Memory ModelWhat a data race actually is, what the Go memory model does and does not promise about one, how to read a race detector report line by line, and the three strategies — confinement, immutability, synchronization — that stop races existing in the first place.1.0 h
- 09MutexesWhen a mutex beats a channel and when it does not, what Lock and Unlock actually guarantee, why RWMutex only pays for itself above a measurable threshold, and the design patterns that keep a lock from leaking out of the type it protects.0.8 h
- 10DeadlocksWhy a deadlock is not a race, the four conditions every deadlock needs, the channel and mutex patterns that produce them, how to read a goroutine dump when the runtime detector stays silent, and why consistent lock ordering is the whole of the cure.1.5 h
- 11Atomic OperationsThe seven operations sync/atomic gives you and what each one costs, why an atomic store is not a cheap load, how atomics establish happens-before, and the three shapes no atomic can express — multi-value invariants, composed operations, and state changes that carry a side effect.1.6 h
- 12The sync Packagesync.Once, sync.Map, sync.Pool and sync.Cond: what each one actually promises, why sync.Map's Go 1.24 rewrite invalidated most of what is written about it, and the failures none of them are data races — a cached error, a dropped update, a borrowed buffer, a wakeup that goes to the wrong goroutine.1.5 h
P3 context & cancellation5 h
- 13Contextcontext.Context: how a cancellation, a deadline and a request-scoped value travel down a tree of goroutines, why a child reports the error that ended the tree rather than the constructor that made it, and what defer cancel() actually releases — measured, and it is not a goroutine.1.3 h
- 14Error Handling in Concurrent CodeThe go keyword discards every return value, so every goroutine that can fail needs a path back that you built on purpose: an error channel, a result struct, or errgroup — which turns out to allocate less than the code it replaces.1.7 h
- 15Graceful ShutdownGraceful is four separate promises, not one, and the window you have to keep them in belongs to the platform. Signals as contexts, the four holes in Server.Shutdown, draining workers without panicking, and what to abandon when the budget runs out.1.8 h
P4 production practices7 h
- 16Testing Concurrent CodeA passing concurrent test is one interleaving that happened to work. testing/synctest, goroutine leak detection as a proof rather than a sample, what a clean -race run is actually worth, and the search that finds what neither can.2.5 h
- 17Rate Limiting and Flow ControlWhen work arrives faster than you can do it, somebody waits. Token buckets, semaphores, backpressure and circuit breakers are four answers to one question -- who waits, where, and what it costs them there.2.1 h
- 18Common Bugs and Code ReviewWhich layer catches which concurrency bug, measured against a sixteen-bug corpus chosen one per chapter: go test found none, go vet three, staticcheck two, the race detector one more, and eleven were caught by nothing. What is left is a protocol, a lifetime or an invariant — three questions, and the review procedure built on them.2.8 h
P5 debugging & performance5 h
- 19Debugging Concurrent ProgramsA concurrent bug lives in an interleaving, not in a state, so stopping and looking is the one reflex that cannot work. Four views of a running program and what each costs to take, the labels missing from the dump you get, the two profiles that report health while switched off, and the flight recorder that was already running.2.1 h
- 20Performance OptimizationThe same three optimisations, measured two ways, reaching opposite conclusions. What a hot frame licenses you to do, Amdahl as arithmetic on a profile you took, whether concurrency is the answer at all, contention as a curve rather than a number, and the seven changes that made it worse.3.1 h
P6 advanced topics4 h
- 21Scheduler and Runtime InternalsFive artifacts this book already printed and left unexplained, and the machinery underneath them: which of G, M and P you run out of, why work stealing does not balance load, what one blocking syscall costs in threads, and the ten years it took to preempt a tight loop.2.2 h
- 22What Held, and What Did NotTwenty-one chapters of advice, composed into one crawler, run for twenty minutes against twelve predictions registered beforehand. Nine held. What the other three cost, what a control run took away, and the class of failure whose signal is a slope rather than a value.1.7 h
Twenty minutes. Twelve predictions. One trace.
The book ends by composing its own advice into a crawler and running it against predictions registered in writing. This is that run, as recorded.