如何在golang中复制地图?
How to copy a map in golang?
我可以提供将地图分解为 2 个切片的示例:
func decomposeMap(m map[string]int) ([]string, []int) {
var i uint
l := len(m)
keys, values := make([]string, l), make([]int, l)
for keys[i], values[i] = range m {
i++
}
return keys, values
}
但是我写地图复制失败了:
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
for id, m2[id] = range m {} // error - id is not declared
for id, m2[id] := range m {} // error with m2[id] already declared
// id should not be accessible here, it should exist only inside loop
return m2
}
我可以将 id 声明为 var,但我不希望它在 for 循环之外可用。我如何混合赋值和声明,例如:for id:=, m[id]= range m {}
?
所以它将在 for 循环内声明索引,并且在外部无法访问?
id
变量必须在for
之前声明,因为不能使用m2[id]
.
的短变量声明
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
var id string
for id, m2[id] = range m {
}
return m2
}
但是!这不会复制地图! 键仅在 m2[id]
已被评估后才分配给 id
,因此此循环会将值分配给上一次迭代的键,这不是复制,这是“洗牌”!
这基本上是一个元组分配(键和值分配给 id, m2[id]
)。 Spec: Assignments:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
所以首先 id
和 m2[id]
被评估(包括索引表达式),所以 id
没有“尚未”改变,所以使用上一次迭代的值,只有在这之后才会分配新的键和值。
要演示,请参阅:
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
m2 := copyMap(m)
fmt.Println(m2)
输出(在 Go Playground 上尝试):
map[:1 one:2 two:3]
这些值被分配给不同的键(与源映射中的不同),并且在第一次迭代中一个值被分配给空字符串键(id
的默认值为零)。
要复制地图,只需使用:
for id, v := range m {
m2[id] = v
}
或者如果您想避免临时分配:
for id := range m {
m2[id] = m[id]
}
我可以提供将地图分解为 2 个切片的示例:
func decomposeMap(m map[string]int) ([]string, []int) {
var i uint
l := len(m)
keys, values := make([]string, l), make([]int, l)
for keys[i], values[i] = range m {
i++
}
return keys, values
}
但是我写地图复制失败了:
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
for id, m2[id] = range m {} // error - id is not declared
for id, m2[id] := range m {} // error with m2[id] already declared
// id should not be accessible here, it should exist only inside loop
return m2
}
我可以将 id 声明为 var,但我不希望它在 for 循环之外可用。我如何混合赋值和声明,例如:for id:=, m[id]= range m {}
?
所以它将在 for 循环内声明索引,并且在外部无法访问?
id
变量必须在for
之前声明,因为不能使用m2[id]
.
func copyMap(m map[string]int) map[string]int {
m2 := make(map[string]int, len(m))
var id string
for id, m2[id] = range m {
}
return m2
}
但是!这不会复制地图! 键仅在 m2[id]
已被评估后才分配给 id
,因此此循环会将值分配给上一次迭代的键,这不是复制,这是“洗牌”!
这基本上是一个元组分配(键和值分配给 id, m2[id]
)。 Spec: Assignments:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
所以首先 id
和 m2[id]
被评估(包括索引表达式),所以 id
没有“尚未”改变,所以使用上一次迭代的值,只有在这之后才会分配新的键和值。
要演示,请参阅:
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
m2 := copyMap(m)
fmt.Println(m2)
输出(在 Go Playground 上尝试):
map[:1 one:2 two:3]
这些值被分配给不同的键(与源映射中的不同),并且在第一次迭代中一个值被分配给空字符串键(id
的默认值为零)。
要复制地图,只需使用:
for id, v := range m {
m2[id] = v
}
或者如果您想避免临时分配:
for id := range m {
m2[id] = m[id]
}