The Go's map semantics are as follows:

type T struct {
    X int
}
m := make(map[int]T)
m[0] = T{}
m[0].x = 42 // won't compile

That's why the only three operations a map supports is adding (or replacing) of its elements, getting them back and deleting them.

A map is not safe for concurrent use, so in order to do any of those three operations on the same map concurrently, you need to protect it in one way or another.

Statssync.Mutex

Now you can see that it's pretty OK to roll like this:

  1. Access the map itself to get a value bound to a key in a concurrent-safe way (say, by holding a lock).
  2. Lock the mutex on that variable and operate on it. That does not involve the map at all.

The only remaining possible problem is as follows. Suppose you're protecting the access to your map with a lock. So you grab the lock, obtain the value bound to a key, by copying it to a variable, release the lock and work with the copy of the value.

Now while you're working with the copy of that value another goroutine is free to update the map by deleting the value or replacing it.

StatsStats