You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言Map交换行为存在差异的原因探究

Go语言Map复制行为差异的原因解析

问题背景

一直以来我认为Go语言中Map是引用类型,传递的仅为Map头部指针,无法直接实现复制。但以下示例中两种复制方式的结果存在明显差异,想明确背后的原因:

示例代码

// go version go1.19.6 linux/amd64

var globalMap = map[int]string{
    0: "foo",
    1: "bar",
}

func copyGlobalMap() map[int]string {
    copiedMap := make(map[int]string)
    globalMap, copiedMap = copiedMap, globalMap

    return copiedMap
}

func copyMap(sourceMap map[int]string) map[int]string {
    copiedMap := make(map[int]string)
    sourceMap, copiedMap = copiedMap, sourceMap

    return copiedMap
}

func main() {
    fmt.Println("--- Example 1 ----")

    copiedMap := copyMap(globalMap)
    globalMap[1] = "moo"

    fmt.Printf("Original map %+v\n", globalMap)
    fmt.Printf("Copied map %+v\n", copiedMap)

    fmt.Println("--- Example 2 ----")

    copiedMap = copyGlobalMap()
    globalMap[1] = "moo"

    fmt.Printf("Original map %+v\n", globalMap)
    fmt.Printf("Copied map %+v\n", copiedMap)
}

运行输出

--- Example 1 ----
Original map map[0:foo 1:moo]
Copied map map[0:foo 1:moo]
--- Example 2 ----
Original map map[1:moo]
Copied map map[0:foo 1:moo]

差异原因分析

核心区别在于操作的是全局变量本身,还是函数参数的引用副本:

示例1(copyMap函数)的本质

调用copyMap(globalMap)时,sourceMap是globalMap引用的一个副本——两者指向同一个底层Map结构,但sourceMap是函数内部的局部变量。
函数内的交换操作sourceMap, copiedMap = copiedMap, sourceMap,仅交换了两个局部变量的引用:

  • 交换前:sourceMap指向原全局Map,copiedMap指向新创建的空Map
  • 交换后:sourceMap指向空Map,copiedMap指向原全局Map
    但这个交换完全不影响外部的globalMap变量,它依然指向原来的底层Map。后续修改globalMap[1] = "moo"是直接修改原底层Map,而copiedMap也指向该Map,所以两者输出一致。

示例2(copyGlobalMap函数)的本质

copyGlobalMap直接操作全局变量globalMap:

  • 先创建空的copiedMap
  • 交换操作后,全局变量globalMap指向新的空Map,copiedMap则指向原来的全局Map数据
    后续修改globalMap[1] = "moo",是对新的空Map进行写入,而copiedMap保存的是原有的完整数据,因此两者完全独立,呈现出“复制”的效果。

补充说明

这种全局变量交换的写法并非真正的Map复制,而是转移全局Map的引用,让全局变量指向新的空Map,以此实现“快照”效果。如果需要通用的Map复制方法,应该遍历原Map的键值对逐个写入新Map:

func realCopyMap(source map[int]string) map[int]string {
    res := make(map[int]string, len(source))
    for k, v := range source {
        res[k] = v
    }
    return res
}

内容的提问来源于stack exchange,提问作者Paperclip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:23:13