如何在迭代常规地图时插入并发地图?
How to upsert into concurrent map while iterating over regular map?
我需要一个 string
的映射作为键和唯一(没有欺骗)int64
数组作为值,所以我决定使用类似下面的东西,这样值就可以作为一个集合。
var customerCatalog = make(map[string]map[int64]bool)
上面的地图填充了一些数据。现在我正在尝试通过阅读上面的常规 customerCatalog
地图在 golang 中填充我的 concurrent map 但我收到错误:
for k, v := range customerCatalog {
r.customerCatalog.Upsert(k, v, func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
typedNewValue := newValue.([]int64)
if !exists {
return typedNewValue
}
typedValueInMap := valueInMap.([]int64)
return append(typedValueInMap, typedNewValue...)
})
}
这是我遇到的错误。我正在使用 upsert 方法,如图所示 here
panic: interface conversion: interface {} is map[int64]bool, not []int64
我做错了什么?
我相信minimal, reproducible, example of your issue would be as follows (playground):
conMap := cmap.New()
v := map[int64]bool{}
updateItemFn := func(exist bool, valueInMap interface{}, newValue interface{}) interface{} {
_ = newValue.([]int64)
return nil
}
conMap.Upsert("foo", v, updateItemFn)
注意:我已经删除了循环等,因为这与恐慌无关。但是您应该注意,因为循环遍历 map[string]map[int64]bool
,所以 v
的类型将是 map[int64]bool
.
Upsert
函数在map中查找key,然后将它和你传入的value
传给函数。
所以你的函数正在接收一个 map[int64]bool
并且它做的第一件事就是断言这是一个 []int64
(这将失败,因为它不是)。要解决此问题,您需要将 map[int64]bool
转换为 []int64
。这可以在调用 Upsert
之前完成,也可以在 UpsertCb
的实现中完成,如下所示 (playground):
conMap := cmap.New()
conMap.Set("foo", []int64{5, 6})
v := map[int64]bool{
1: true,
}
updateItemFn := func(exist bool, valueInMap interface{}, newValue interface{}) interface{} {
m := newValue.(map[int64]bool)
a := make([]int64, 0, len(m))
for k := range m {
a = append(a, k)
}
if valueInMap == nil { // New value!
return a
} else {
typedValueInMap := valueInMap.([]int64)
return append(typedValueInMap, a...)
}
return a
}
conMap.Upsert("foo", v, updateItemFn)
fmt.Println(conMap.Get("foo"))
以上内容为了说明要点已保持简单;实际上,您可能希望将所有值添加到地图中以避免重复。
我需要一个 string
的映射作为键和唯一(没有欺骗)int64
数组作为值,所以我决定使用类似下面的东西,这样值就可以作为一个集合。
var customerCatalog = make(map[string]map[int64]bool)
上面的地图填充了一些数据。现在我正在尝试通过阅读上面的常规 customerCatalog
地图在 golang 中填充我的 concurrent map 但我收到错误:
for k, v := range customerCatalog {
r.customerCatalog.Upsert(k, v, func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
typedNewValue := newValue.([]int64)
if !exists {
return typedNewValue
}
typedValueInMap := valueInMap.([]int64)
return append(typedValueInMap, typedNewValue...)
})
}
这是我遇到的错误。我正在使用 upsert 方法,如图所示 here
panic: interface conversion: interface {} is map[int64]bool, not []int64
我做错了什么?
我相信minimal, reproducible, example of your issue would be as follows (playground):
conMap := cmap.New()
v := map[int64]bool{}
updateItemFn := func(exist bool, valueInMap interface{}, newValue interface{}) interface{} {
_ = newValue.([]int64)
return nil
}
conMap.Upsert("foo", v, updateItemFn)
注意:我已经删除了循环等,因为这与恐慌无关。但是您应该注意,因为循环遍历 map[string]map[int64]bool
,所以 v
的类型将是 map[int64]bool
.
Upsert
函数在map中查找key,然后将它和你传入的value
传给函数。
所以你的函数正在接收一个 map[int64]bool
并且它做的第一件事就是断言这是一个 []int64
(这将失败,因为它不是)。要解决此问题,您需要将 map[int64]bool
转换为 []int64
。这可以在调用 Upsert
之前完成,也可以在 UpsertCb
的实现中完成,如下所示 (playground):
conMap := cmap.New()
conMap.Set("foo", []int64{5, 6})
v := map[int64]bool{
1: true,
}
updateItemFn := func(exist bool, valueInMap interface{}, newValue interface{}) interface{} {
m := newValue.(map[int64]bool)
a := make([]int64, 0, len(m))
for k := range m {
a = append(a, k)
}
if valueInMap == nil { // New value!
return a
} else {
typedValueInMap := valueInMap.([]int64)
return append(typedValueInMap, a...)
}
return a
}
conMap.Upsert("foo", v, updateItemFn)
fmt.Println(conMap.Get("foo"))
以上内容为了说明要点已保持简单;实际上,您可能希望将所有值添加到地图中以避免重复。