Copying a sync type
All primitive types in the sync package follow one hard rule, they should
never be copied.
- sync.Cond
 - sync.Map
 - sync.Mutex
 - sync.RWMutex
 - sync.Once
 - sync.Pool
 - sync.WaitGroup
 
Mistake
This is an example of a data race from copying a sync primitive.
type Counter struct {
  mu sync.Mutex
  counters map[string]int
}
func NewCounter() Counter {
  return Counter{counters: map[string]int{}}
}
// The function receiver here is a value so it is copied instead of referenced
func (c Counter) Increment(name string){
  c.mu.Lock()
  defer c.mu.Unlock()
  c.counters[name]++
}
Fix
Alternatively, we could make Counter.mu a pointer to a sync.Mutex
type Counter struct {
  mu sync.Mutex
  counters map[string]int
}
func NewCounter() Counter {
  return Counter{counters: map[string]int{}}
}
func (c *Counter) Increment(name string){
  c.mu.Lock()
  defer c.mu.Unlock()
  c.counters[name]++
}