Race condition
A race condition is a bug where the result of a program depends on timing: which of two concurrent operations happens first. The code passes most runs and fails some, because the scheduler interleaves the operations differently each time. Races are common anywhere goroutines, threads or processes share state.
How it works
Most races hide a step that looks atomic but is not. count++ is three steps: read the value, add 1, write it back. If two goroutines both read 41, both add 1 and both write 42, one increment is lost. A check-then-act sequence, such as "if the seat is free, book it", has the same shape at a larger scale.
For example, two goroutines each run count++ 1,000 times on a shared count with no lock. The answer should be 2,000, but a run can print 1,734 because 266 increments were overwritten. Guarding the increment with a sync.Mutex (mu.Lock(), count++, mu.Unlock()), or using atomic.Int64, makes it 2,000 every time. go test -race catches the original bug and prints WARNING: DATA RACE with the stack of both goroutines.
Why it matters in production
Races pass code review and most test runs, then show up under production load as wrong totals, double bookings or corrupted maps; Go stops the program with fatal error: concurrent map writes when it detects the last one. Run tests with -race in CI, prefer passing data over channels to sharing it, and use database transactions or idempotent writes when the shared state lives outside the process. A data race is one kind of race condition; code with correct locks can still have a check-then-act race.
See also
On the One2N blog
References
