Go "DATA RACE" in goroutine - Fix in CI
The race detector flags concurrent unsynchronized access where at least one operation is a write. It reports the two goroutines and stacks so you can add the missing synchronization.
What this error means
go test -race fails with WARNING: DATA RACE and two stacks reading/writing the same address. Shared state is mutated from multiple goroutines without a lock.
go
==================
WARNING: DATA RACE
Write at 0x00c0000a4010 by goroutine 8:
example.com/app.(*Counter).Inc()
counter.go:14 +0x...
Previous read at 0x00c0000a4010 by goroutine 7:
example.com/app.(*Counter).Value()
counter.go:18 +0x...
==================Common causes
Unsynchronized shared state
Multiple goroutines read and write the same variable without a mutex or channel.
Closure capturing a loop variable
Goroutines share a captured variable that the loop mutates, racing on it.
How to fix it
Guard shared state with a mutex
- Protect every access to the shared field with the same lock.
Go
mu.Lock()
c.n++
mu.Unlock()Use atomics for counters
- Replace a plain counter with an atomic type so increments are race-free.
Go
var n atomic.Int64
n.Add(1)How to prevent it
- Run go test -race in CI on concurrent code.
- Guard all shared state with a mutex or use atomics.
- Pass loop variables explicitly into goroutines.
Related guides
Go vet "possible misuse of unsafe.Pointer" - Fix in CIFix go vet "possible misuse of unsafe.Pointer" in CI - a uintptr round-trip through unsafe.Pointer broke the…
Go "fork/exec /tmp: permission denied" - Fix in CIFix Go tests failing with "fork/exec /tmp/...: permission denied" in CI - /tmp is mounted noexec or restricte…
Go "panic: test timed out" - Fix in CIFix Go "panic: test timed out after Xm" in CI - a test exceeded the -timeout budget. Fix the hang or raise th…