I'm trying to solve WARNING: DATA RACE here is the code:
package models
import (
"sync"
"time"
)
type Stats struct {
sync.Mutex
request map[int64]int
}
func (s *Stats) PutRequest() {
s.Lock()
s.request[time.Now().Unix()]++
s.Unlock()
}
func (s *Stats) GetRequests() map[int64]int {
s.Lock()
m := s.request
s.Unlock()
return m
}
var Requests = Stats{
sync.Mutex{},
make(map[int64]int),
}
If i change Stats field request into integer then everithing works fine but not with map. How to correctly lock map in Go?
Use sync.RWMutex
func (s *Stats) PutRequest(ut int64) {
s.Lock()
defer s.Unlock()
s.request[ut]++
}
func (s *Stats) GetRequests() map[int64]int {
s.RLock()
defer s.RUnlock()
m := make(map[int64]int, len(s.request))
for k, v := range s.request {
m[k] = v
}
return m
}
The following channel example can be interesting in this case. go by example - stateful goroutines
Anyway you need to copy the map before returning it.
GetRequests
returns the reference to the map, so if other code calls the function and do r/w on the returning map without acquiring the lock, then data race is introduced