Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang fatal error: concurrent map read and map write

Tags:

dictionary

go

Generally speaking (without having access to the code where the error occurs) you have a few options. Here are two of them:

sync.RWMutex

Control access to the map with sync.RWMutex{}. Use this option if you have single reads and writes, not loops over the map. See RWMutex

Here a sample with access control to someMap via someMapMutex:

var (
    someMap      = map[string]string{}
    someMapMutex = sync.RWMutex{}
)

go func() {
    someMapMutex.Lock()
    someMap["key"] = "value"
    someMapMutex.Unlock()
}()

someMapMutex.RLock()
v, ok := someMap["key"]
someMapMutex.RUnlock()
if !ok {
    fmt.Println("key missing")
    return
}
fmt.Println(v)

syncmap.Map

Use a syncmap.Map{} instead of a normal map. This map is already taking care of race issues but may be slower depending on your usage. syncmap.Map{}s main advantage lies with for loops. See syncmap

var (
    someMap = syncmap.Map{}
)

go func() {
    someMap.Store("key", "value")
}()

v, ok := someMap.Load("key")
if !ok {
    fmt.Println("key missing")
    return
}
fmt.Println(v)

// with syncmap, looping over all keys is simple without locking the whole map for the entire loop
someMap.Range(func(key, value interface{}) bool {
    // cast value to correct format
    val, ok := value.(string)
    if !ok {
        // this will break iteration
        return false
    }
    // do something with key/value
    fmt.Println(key, val)

    // this will continue iterating
    return true
})

General Advice

You should test your server with -race option and then eliminate all the race conditions it throws. That way you can easier eliminate such errors before they occur.

go run -race server.go

See golang race detector