将地图的所有元素复制到另一个元素中

时间:2011-09-15 20:08:39

标签: dictionary go copy

鉴于

var dst, src map[K]V

我可以通过

src中的所有条目复制到dst
for k, v := range src {
    dst[k] = v
}

是否有更惯用的方式来做到这一点?

copy仅适用于切片(以及string作为来源)。

3 个答案:

答案 0 :(得分:45)

对我来说这看起来是一个非常好的方式。我不认为将一张地图复制到另一张地图是常见的,只有单线解决方案。

答案 1 :(得分:7)

使用简单的for range循环是最有效的解决方案。

请注意,内置copy无法将src的内存复制到dst的地址,因为它们可能具有完全不同的内存布局。地图增长以适应存储在其中的项目数量。因此,例如,如果你有一个包含一百万个元素的地图,它占用的内存比新创建的新地图要多得多,因此内置copy无法在不分配新内容的情况下复制内存。

如果您的地图很大,如果您可以创建具有足够容量的目标地图以避免重新布局和重新分配(初始容量不限制其大小),则可以加快复制元素,例如:

dst := make(map[K]V, len(src))

for k, v := range src {
    dst[k] = v
}

如果性能不是问题(例如,您正在使用小地图),则可以使用reflect包创建一般解决方案:

func MapCopy(dst, src interface{}) {
    dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src)

    for _, k := range sv.MapKeys() {
        dv.SetMapIndex(k, sv.MapIndex(k))
    }
}

此解决方案不会检查参数是否真的是映射,以及目标不是nil。测试它:

m1 := map[int]string{1: "one", 2: "two"}
m2 := map[int]string{}
MapCopy(m2, m1)
fmt.Println(m2)

m3 := map[string]int{"one": 1, "two": 2}
m4 := map[string]int{}
MapCopy(m4, m3)
fmt.Println(m4)

输出(在Go Playground上尝试):

map[1:one 2:two]
map[one:1 two:2]

答案 2 :(得分:2)

您可以使用github.com/linkosmos/mapop

input :=  map[string]interface{}{
  "Key1": 2,
  "key3": nil,
  "val": 2,
  "val2": "str",
  "val3": 4,
}

input2 := map[string]interface{}{
  "a2": "str",
  "a3": 4,
}

input = mapop.Merge(input, input2)

input{"Key1": 2, "key3": nil, "val": 2, "val2": "str", "val3": 4, "a2": "str", "a3": 4}