maneira legal, go-idiomática de usar um mapa compartilhado

Digamos que eu tivesse um programa com acesso simultâneo a um mapa, assim:

func getKey(r *http.Request) string { ... }

values := make(map[string]int)

http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
  key := getKey(r)
  fmt.Fprint(w, values[key])
})

http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {
  key := getKey(r)
  values[key] = rand.Int()
})

Isso é ruim, já que as gravações de mapa não são atômicas. Então eupoderia usar um mutex de leitura / gravação

func getKey(r *http.Request) string { ... }

values := make(map[string]int)
var lock sync.RWMutex

http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
  key := getKey(r)
  lock.RLock()
  fmt.Fprint(w, values[key])
  lock.RUnlock()
})

http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {
  key := getKey(r)
  lock.Lock()
  values[key] = rand.Int()
  lock.Unlock()
})

O que parece bem, exceto pelo fato de que estamos usando diretamente mutexes e não canais.

O que é uma maneira mais idiomática de implementar isso? Ou este é um daqueles momentos em que um mutex é realmente tudo o que você precisa?

questionAnswers(4)

yourAnswerToTheQuestion