Race conditions
Unsynchronized conflicting access is a correctness bug. Fix the ownership or synchronization story, not just the symptom.
Canonical guidance
- treat races as correctness bugs
- fix the synchronization model, not just the schedule that exposed the bug
- prefer ownership and simpler boundaries over scattered atomics
Use when
- debugging flaky concurrent tests
- reviewing shared mutable state
- interpreting race detector output
Avoid
- sleeps as race fixes
- assuming writes become visible eventually
- calling a race “unlikely” and shipping it
Preferred pattern
- one owner or one synchronization boundary for each shared invariant
Anti-pattern
- one goroutine writing a field while another reads it “only for metrics”
Explanation: This is tempting because the field feels low-value, but races corrupt reasoning about the whole program.
Why
- once accesses are unsynchronized, the program’s behavior is no longer dependable
Related pages
Sources
- The Go Memory Model - Go Team
- Data Race Detector - Go Team