为了调试一些并发问题,我正在将部分代码从处理常规Golang映射切换为处理sync.Map。但是,当我尝试运行新代码时,遇到两个不确定的调试错误。
原始代码块:
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()
新代码块:
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()
}
引发的错误是:
... first argument to append must be slice; have interface {}
... cannot use value (type []int) as type int in array or slice literal
sync_map.Load
返回一个interface{}
,这就是您遇到第一个错误的原因。您必须使用类型断言来获取基础类型:
cur_slice_i, _ := sync_map.Load(cur_h)
cur_slice := cur_slice_i.([]int)
updtd_slice := append(cur_slice, cur_id)
不是以上所述,cur_slice_i可以为nil。即使您先检查并加载,如果有人在另一个goroutine中将其从地图中删除,您在这里也可能会得到nil。
第二个错误再次是类型不匹配:值已经是一个int数组,所以:
sync_map.Store(cur_h, value)
您首次将地图与互斥锁一起使用是正确的。如果您在访问该地图的所有其他goroutine中使用相同的模式,则不应遇到与并发访问地图有关的问题。