๐ŸThe Race DetectorLESSON

The Race Detector

What is a data race?

A data race occurs when two goroutines access the same memory location concurrently and at least one access is a write โ€” with no synchronisation between them. The result is undefined behaviour: corrupted data, crashes, or silent wrong answers that appear intermittently.

Enabling the race detector

Append -race to any Go command:

The race detector is built on ThreadSanitizer. It instruments memory accesses at compile time and reports races at runtime when they actually occur.

Reading a race report

The report shows: the racing memory address, which goroutine performed each access, the source location of each access, and where each goroutine was created. Fix by adding a mutex, channel, or atomic around the shared variable.

Fixing races

Three canonical fixes:

When to run -race

ContextRecommendation
CI pipelineAlways โ€” run go test -race ./... on every PR
Local developmentEnable for concurrent packages during development
Production binaryAvoid โ€” 2โ€“20ร— overhead; only for debugging
BenchmarksNever โ€” overhead skews results

Always run -race in CI. The detector only fires when a race actually executes, so 100% code coverage under -race greatly increases confidence.

-race overhead

The race detector adds approximately:

  • 5โ€“15ร— slowdown in execution speed
  • 5โ€“10ร— increase in memory usage

This is why production binaries ship without it. Accept the overhead in test environments.

Test coverage flags

While not race-related, often used together:

Knowledge Check

What condition defines a data race?

Why should -race never be used for benchmarks?

The race detector only fires when a race actually executes at runtime. What does this imply about test coverage?