A data race occurs when two or more goroutines access the same memory location concurrently and at least one writes to it. A shared variable is not safe merely because each goroutine performs a simple-looking operation. section 8.4.1
Two increments, one lost
Start with `i := 0` and run `i++` in each of two goroutines. Each increment reads `i`, adds one, then writes it back. If both read 0 before either writes, both write 1; if their increments complete in sequence, the result is 2. Running the example with `-race` reports a data race. section 8.4.1
Choose a fix that fits who needs to access the value:
- Use `atomic.AddInt64(&i, 1)` when the shared operation is an atomic increment. section 8.4.1
- Put every access that needs protection inside the same mutex-protected critical section. section 8.4.1 section 9.10
- Have goroutines send values on a channel and let one goroutine update the total. section 8.4.1
A lock only helps if it protects the actual shared data for the entire access. Copying a map variable under a read lock does not copy its data buckets: iterating over that map after unlocking can race with a writer. Keep the lock through a lightweight iteration, or copy the map's entries while locked and process the copy afterward. section 9.10
func (c *Cache) AverageBalance() float64 {
c.mu.RLock()
balances := c.balances #1
c.mu.RUnlock()
sum := 0.
for _, balance := range balances { #2
sum += balance
}
return sum / float64(len(balances))
}
The read lock ends before iteration, but `balances` still refers to the shared map data; a concurrent `AddBalance` can write while the loop reads. section 9.10
The same aliasing question matters for slices. Concurrent `append` calls on a full slice use new backing arrays in the shown example; with spare capacity, both can write the same backing-array location. Give each goroutine its own copy when it must append independently. Also avoid copying a `sync.Mutex`: a value-receiver method can copy the mutex while retaining access to the same map, so the calls no longer share a critical section. Use a pointer receiver or a properly initialized pointer to the mutex; `go vet` can flag a lock passed by value. section 9.9 section 9.14



