Programming Languages

Go Data Race Patterns and Prevention

https://www.uber.com/en-CZ/blog/data-race-patterns-in-go/

Core Patterns & Solutions

Read-Write Conflicts

// Bad
func worker(counter *int) {
    *counter++  // Race condition
}

// Good
func worker(counter *atomic.Int64) {
    counter.Add(1)  // Atomic operation
}

Map Access

// Bad
m := make(map[string]int)
go func() { m["x"] = 1 }()
go func() { _ = m["x"] }()

// Good
var mu sync.RWMutex
m := make(map[string]int)
go func() {
    mu.Lock()
    m["x"] = 1
    mu.Unlock()
}()

Slice Access

// Bad
s := make([]int, 0)
go func() { s = append(s, 1) }()

// Good
var mu sync.Mutex
s := make([]int, 0)
go func() {
    mu.Lock()
    s = append(s, 1) 
    mu.Unlock()
}()

Key Prevention Strategies:

Use sync/atomic for simple counters

  1. sync.Mutex for complex data structures
  2. channels for communication
  3. sync.RWMutex when reads > writes
  4. Use -race flag during testing

Detection Tools:

Best Practices:

Time Complexity Impact:


🎰