在 Go 语言编程中,我们常常需要处理键值对集合,即 map。特别是在递归处理文件路径时,可能需要将多个 map 合并成一个。这个操作相当于集合的并集操作:将一个 map 中的键值对更新到另一个 map 中。本文将介绍如何在 Go 中合并两个 map。
使用 Go 1.21 及更高版本的 maps.Copy
函数
自 Go 1.21 起,Go 语言提供了一个新的标准库函数 maps.Copy
,可以方便地将一个 map 的所有键值对复制到另一个 map 中。
示例代码
package main
import (
"fmt"
"maps"
)
func main() {
src := map[string]int{
"one": 1,
"two": 2,
}
dst := map[string]int{
"two": 42,
"three": 3,
}
maps.Copy(dst, src)
fmt.Println("src:", src)
fmt.Println("dst:", dst)
}
输出结果
src: map[one:1 two:2]
dst: map[one:1 three:3 two:2]
在上面的例子中,我们定义了两个 map src
和 dst
,并使用 maps.Copy
函数将 src
中的键值对复制到 dst
中。最终,dst
包含了两个 map 的所有键值对,其中 src
中的键值对覆盖了 dst
中相同键的值。
使用 Go 1.18 到 Go 1.20 的 golang.org/x/exp/maps.Copy
函数
在 Go 1.18 到 Go 1.20 版本中,可以使用 golang.org/x/exp/maps
包中的 Copy
函数来实现相同的功能。
示例代码
package main
import (
"fmt"
"golang.org/x/exp/maps"
)
func main() {
src := map[string]int{
"one": 1,
"two": 2,
}
dst := map[string]int{
"two": 42,
"three": 3,
}
maps.Copy(dst, src)
fmt.Println("src:", src)
fmt.Println("dst:", dst)
}
输出结果
src: map[one:1 two:2]
dst: map[one:1 three:3 two:2]
需要注意的是,在 Go 1.18.x 到 1.19.x 版本中,Copy
函数要求 map 的键类型必须是具体类型,而不是接口类型。如果键类型是接口类型,编译器将无法通过编译。
!!!错误示例!!!
package main
import (
"fmt"
"io"
"golang.org/x/exp/maps"
)
func main() {
var src, dst map[io.Reader]int
maps.Copy(dst, src)
fmt.Println("src:", src)
fmt.Println("dst:", dst)
}
编译错误
./prog.go:12:11: io.Reader does not implement comparable
在 Go 1.20 及更高版本中,这一限制已被移除。
手动合并 map
在不使用上述新功能的情况下,我们也可以手动迭代一个 map,并将其键值对添加到另一个 map 中。
示例代码
package main
import (
"fmt"
)
func mergeMaps(dst, src map[string]int) {
for key, value := range src {
dst[key] = value
}
}
func main() {
src := map[string]int{
"one": 1,
"two": 2,
}
dst := map[string]int{
"two": 42,
"three": 3,
}
mergeMaps(dst, src)
fmt.Println("src:", src)
fmt.Println("dst:", dst)
}
输出结果
src: map[one:1 two:2]
dst: map[one:1 three:3 two:2]