问题
In order to debug some concurrency issues, I am in the process of switching part of my code from working on a regular Golang map to working on a sync.Map. However, when I try to run my new code, I am encountering two errors that I'm not sure how to debug.
The original code block:
sync_mutex.Lock()
if _, ok := the_map[cur_h]; ok {
the_map[cur_h] = append(the_map[cur_h], cur_id)
} else {
value := []int{cur_id}
the_map[cur_h] = value
}
sync_mutex.Unlock()
The new code block:
if _, ok := sync_map.Load(cur_h); ok {
sync_mutex.Lock()
cur_slice, _ := sync_map.Load(cur_h)
updtd_slice := append(cur_slice, cur_id) // error #1
sync_map.Store(cur_h, updtd_slice)
map_mutex.Unlock()
} else {
map_mutex.Lock()
value := []int{cur_id}
sync_map.Store(cur_h, []int{value}) // error #2
sync_mutex.Unlock()
}
The error that is being thrown is:
... first argument to append must be slice; have interface {}
... cannot use value (type []int) as type int in array or slice literal
回答1:
sync_map.Load
returns an interface{}
, that's the reason why you got that first error. You have to use type assertions to get the underlying type:
cur_slice_i, _ := sync_map.Load(cur_h)
cur_slice := cur_slice_i.([]int)
updtd_slice := append(cur_slice, cur_id)
Not that above, cur_slice_i can be nil. Even though you first check and load, if somebody removes that key from the map in another goroutine, you may get nil here.
The second error is again a type mismatch: value is an int array already, so:
sync_map.Store(cur_h, value)
Your first use of map with a mutex is correct. If you use the same pattern in all the other goroutines that access that map, then you shouldn't run into problems related to concurrent access to map.
来源:https://stackoverflow.com/questions/59299470/working-with-slices-and-golang-sync-map-structure