Go interviewer course · Reference 0002

Concurrency desk sheet

Choose the tool
by its job

Goroutine for work. Channel for communication. WaitGroup for completion. Mutex for shared state. Select for competing events.

Ten small patterns

Use → guarantee → common trap

#PatternWhat it gives youCommon trap
1wg.Go(f) + wg.Wait()Start one task and join it.Letting main exit before work finishes.
2Several wg.Go callsCompletion of all tasks, not task order.Assuming launch order is finish order.
3Unbuffered chan TA direct sender/receiver handoff.Sending and receiving sequentially in one goroutine.
4Buffered chan TLimited decoupling up to capacity.Treating capacity as a deadlock cure.
5close(ch) + range chA clear “no more values” signal.Receiver closes a sender-owned channel.
6chan<- T / <-chan TCompile-time send/receive ownership.Every stage tries to close every channel.
7select + timeoutWait for the first available event.Late sender blocks after the receiver leaves.
8Jobs → workers → resultsBounded parallel processing.Closing results before every sender exits.
9sync.MutexExclusive access to one invariant.Locking writes but not reads.
10sync.RWMutexConcurrent readers, exclusive writers.Using it without a measured need.

Rules worth memorizing

Ownership, lifetime, ordering

Ownership

  • The goroutine that knows no more values will be sent closes the channel.
  • Closing is optional when receivers already know how many values to receive.
  • Never close merely to release a blocked sender; its next send panics.

Lifetime

  • Every goroutine needs a stop condition.
  • WaitGroup joins tasks; it does not carry results or errors.
  • A sleep changes timing, not correctness.

Ordering

  • A matching channel operation can establish ordering.
  • An Unlock can order a later Lock.
  • No synchronization edge means no visibility guarantee.

Closed channel

Receives drain buffered values, then return the zero value with ok == false. A send panics.

Nil channel

Send and receive block forever. A nil channel disables its case inside select.

Copied lock

Do not copy a mutex or a value containing one after first use. Prefer pointer receiver methods.

Run and verify

Three commands

# Run one
go run ./examples/concurrency/05-close-and-range

# Compile and execute tests for every package
go test ./...

# Run an example with runtime race instrumentation
go run -race ./examples/concurrency/09-mutex-counter

The race detector is dynamic: it can detect only races exercised by the run.