ZetCode

Golang maps.Copy

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 Go 中使用 `maps.Copy` 函数。我们将通过实际示例介绍 Map 复制操作。

`maps.Copy` 函数将一个 Map 中的所有键值对复制到另一个 Map 中。它是 Go 实验性 maps 包的一部分。

此函数可用于复制 Map 数据或合并 Map。它会处理目标 Map 中现有键的覆盖。

基本的 maps.Copy 示例

`maps.Copy` 最简单的用法是将一个 Map 中的所有元素复制到另一个 Map 中。两个 Map 的键和值类型必须相同。

basic_copy.go
package main

import (
    "fmt"
    "maps"
)

func main() {
    src := map[string]int{"a": 1, "b": 2}
    dst := make(map[string]int)
    
    maps.Copy(dst, src)
    
    fmt.Println("Copied map:", dst)
}

我们创建一个源 Map 和一个空的 Map。复制后,目标 Map 将包含源 Map 中的所有键值对。

覆盖现有键

`maps.Copy` 会覆盖目标 Map 中已有的键。此示例演示了此行为。

overwrite_keys.go
package main

import (
    "fmt"
    "maps"
)

func main() {
    src := map[string]int{"a": 1, "b": 2}
    dst := map[string]int{"a": 5, "c": 3}
    
    maps.Copy(dst, src)
    
    fmt.Println("Result after copy:", dst)
}

目标 Map 的“a”键将被源 Map 的值覆盖。“b”键将被添加,“c”键保持不变。

在不同的 Map 类型之间复制

如果类型兼容,我们可以在具有不同底层类型的 Map 之间复制。此示例将从 `map[int]string` 复制到 `map[int]string`。

different_types.go
package main

import (
    "fmt"
    "maps"
)

func main() {
    src := map[int]string{1: "one", 2: "two"}
    dst := make(map[int]string)
    
    maps.Copy(dst, src)
    
    fmt.Println("Copied map:", dst)
}

只要键和值类型匹配,该函数就可以与任何 Map 类型一起使用。目标 Map 将接收源 Map 中的所有元素。

复制 Nil Map

`maps.Copy` 可以妥善处理 nil Map。此示例显示了 nil 源 Map 和目标 Map 的行为。

nil_maps.go
package main

import (
    "fmt"
    "maps"
)

func main() {
    var src map[string]int
    dst := make(map[string]int)
    
    // Copy from nil map
    maps.Copy(dst, src)
    fmt.Println("Copy from nil:", dst)
    
    // Copy to nil map
    src = map[string]int{"a": 1}
    var nilDst map[string]int
    maps.Copy(nilDst, src)
    fmt.Println("Copy to nil:", nilDst)
}

从 nil 源复制不会执行任何操作。复制到 nil 目标会导致 panic,这与常规 Map 操作类似。

复制大型 Map

`maps.Copy` 可以高效地处理大型 Map。此示例对复制性能进行了基准测试。

large_maps.go
package main

import (
    "fmt"
    "maps"
    "time"
)

func main() {
    largeMap := make(map[int]int, 1_000_000)
    for i := 0; i < 1_000_000; i++ {
        largeMap[i] = i * 2
    }
    
    dst := make(map[int]int, len(largeMap))
    
    start := time.Now()
    maps.Copy(dst, largeMap)
    elapsed := time.Since(start)
    
    fmt.Printf("Copied 1,000,000 elements in %v\n", elapsed)
    fmt.Println("Sample values:", dst[0], dst[999999])
}

该函数可以高效地复制所有元素,同时保持 Map 的性能。预先分配目标 Map 可以提高复制速度。

复制包含 Struct 值的 Map

`maps.Copy` 可以与包含 Struct 值的 Map 一起使用。此示例演示了复制复杂值类型。

struct_values.go
package main

import (
    "fmt"
    "maps"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    src := map[string]Person{
        "alice": {"Alice", 30},
        "bob":   {"Bob", 25},
    }
    
    dst := make(map[string]Person)
    maps.Copy(dst, src)
    
    fmt.Println("Copied people:", dst)
}

该函数对 Struct 值执行浅拷贝。复制后,两个 Map 都将包含相同的 Person 值。

实际示例:合并配置

这个实际示例展示了如何使用 `maps.Copy` 来合并配置 Map。

merge_configs.go
package main

import (
    "fmt"
    "maps"
)

func main() {
    defaultConfig := map[string]string{
        "theme": "dark",
        "lang":  "en",
        "cache": "true",
    }
    
    userConfig := map[string]string{
        "theme": "light",
        "proxy": "localhost:8080",
    }
    
    // Merge user config over defaults
    maps.Copy(defaultConfig, userConfig)
    
    fmt.Println("Merged configuration:")
    for k, v := range defaultConfig {
        fmt.Printf("%s: %s\n", k, v)
    }
}

用户首选项会覆盖默认值,同时保留未指定设置。这种模式在应用程序配置系统中很常见。

来源

Go 实验性 maps 包文档

本教程通过复制和合并 Map 的各种场景的实际示例,介绍了 Go 中的 `maps.Copy` 函数。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Go 教程