Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
Golang Pitfalls: Concurrency Foundations
Source material: mistakes #55-60 from 100 Go Mistakes and How to Avoid Them (teivah/100-go-mistakes).
Apply these rules when reasoning about basic Go concurrency.
55. Mixing up concurrency and parallelism (#55)
- Concurrency is about structure (breaking a problem into independently executible parts); parallelism is about execution (running parts at the same time).
- Concurrency provides the structure that enables parallelism.
56. Thinking concurrency is always faster (#56)
- Concurrency is not automatically faster. Creating goroutines and scheduling has costs.
- Parallel merge sort on 4 cores, naively spawning goroutines for each half, was ~an order of magnitude slower than sequential for 10k elements.
- The fix: only parallelize workloads above a threshold (e.g., a
maxslice size, benchmarked for your machine). - Validate assumptions with benchmarks and profiling; start sequential when unsure.
57. Being puzzled about channels vs. mutexes (#57)
- Parallel goroutines need synchronization (exclusive access to a shared resource) → mutexes.
- Concurrent goroutines need coordination/orchestration (signaling, aggregation, ownership transfer) → channels.
- Don't force channels everywhere because Go "promotes sharing memory by communication." Both are complementary tools.
58. Not understanding race problems (#58)
- Data race: two or more goroutines access the same memory location simultaneously and at least one writes — undefined behavior.
- Race condition: behavior depends on the sequence/timing of uncontrolled events. An application can be data-race-free yet non-deterministic.
- Prevent data races with
sync/atomic, mutexes, or channels; usego test -race.
59. Not understanding workload type impacts (#59)
- CPU-bound workloads: optimal goroutine count ≈
runtime.GOMAXPROCS(default = number of CPU cores). - I/O-bound workloads: the count depends on the external system, not the cores.
- Identify the workload type before sizing goroutine pools.
60. Misunderstanding Go contexts (#60)
context.Contextcarries a deadline, a cancellation signal, and a key-value list across API boundaries.- Deadlines: from a duration (
context.WithTimeout) or a time (context.WithDeadline). - Cancellation:
Done()returns a receive-only channel that is closed on cancel/deadline — closure is broadcast to all consumers (the only channel action received by all goroutines). - Functions the user waits on should take a context so callers can abort them.
Cross-References
- → See
fabianoflorentino/golang-agent-skills@golang-concurrencyfor the full goroutine, channel, and sync-primitive patterns - → See
fabianoflorentino/golang-agent-skills@golang-contextfor idiomatic context.Context creation, cancellation, and propagation - → See
fabianoflorentino/golang-agent-skills@golang-testingfor race detection and goroutine-leak testing - → See
fabianoflorentino/golang-agent-skills@golang-benchmarkfor validating decisions with measurements

