Data races and the memory model in Go
Summary
A detailed explanation of Go's memory model and data races, with examples showing why unsynchronized shared reads/writes can race. It covers synchronization primitives (atomic, mutex, WaitGroup, channel close, sync.Once) and how they ensure visibility of writes across goroutines, plus testing with the race detector.