为什么Go map交换行为不同

vs91vp4v  于 2023-04-18  发布在  Go
关注(0)|答案(1)|浏览(112)

也许这是一个非常菜鸟的问题,但我不能完全理解为什么这种差异会发生在我的复制方法。
到目前为止,我一直假设你不能复制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的行为和通常一样,思维导图是“* 纠缠 *”的。但是第二个例子似乎暗示了一个单独的副本被实现了。
有谁能解释一下为什么这(看起来?)有效?
注意:在一个代码库中观察到这样的全局交换,对全局缓存进行了快照。首先,我不相信它工作正常,但似乎是。

abithluo

abithluo1#

这个函数不复制任何东西。

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

    return copiedMap
}
源代码描述
copiedMap := make(map[int]string)创建新的空Map
sourceMap, copiedMap = copiedMap, sourceMap交换两个变量的值。copiedMap现在定位***原始***sourceMap;sourceMap现在定位您创建的新的空Map。
return copiedMapcopiedMap的当前值返回给调用者。这将是原始的sourceMap

如果您这样做:

src := map[int]string{ 1:"one", 2:"two", 3:"three" }
cpy := copyMap(src)
src[4] = "quatre"

你会发现srccpy现在都有4个元素。
如果你真的想创建一个Map的副本,它只是:

func copyMap(src map[int]string) map[int]string {
    cpy := make(map[int]string)
    for k, v := range src {
        cpy[k] = v
    }
    return cpy
}

相关问题