Code-Memo

Concurrency patterns and best practices

Fan-out / fan-in

Multiple workers read jobs from a channel; another stage merges results.

Worker pool

Fixed N goroutines pulling from jobs channel; results go to results.

Pipeline

Stages connected by channels; each stage does one transformation. Watch for backpressure: unbuffered stages block upstream naturally; buffered stages need sizing.

errgroup

golang.org/x/sync/errgroup runs goroutines and returns the first error, with optional cancellation via context.

g, ctx := errgroup.WithContext(ctx)
for _, item := range items {
	item := item
	g.Go(func() error { return process(ctx, item) })
}
return g.Wait()
Don’t communicate by sharing memory…

share memory by communicating (Rob Pike) — but mutexes are fine when ownership is clearer than channel choreography.

Avoid leaks

Always ensure goroutines exit: tie to ctx.Done(), close upstream, or use WaitGroup.

Timeouts

Wrap external calls with context.WithTimeout.

Testing concurrency

Use -race in CI; stress tests with go test -count=100 for flaky ordering bugs.