为什么一个函数中的映射值会受到另一函数中映射条目的影响?

2023-12-11

这是我的代码:

func test(v map[string]string) {
    v["foo"] = "bar"
}

func main() {
    v := make(map[string]string)
    test(v)
    fmt.Printf("%v\n", v) // prints map[foo:bar]
}

我对 Go 很陌生,但据我所知,因为我将地图值传递给test()而不是指向地图的指针,test()函数应该修改映射的不同变量,因此不会影响变量的值main()。我本来希望它能打印出来map[]。我测试了不同的场景:

type myStruct struct {
    foo int
}

func test2(v myStruct) {
    v.foo = 5
}

func main() {
    v := myStruct{1}
    test2(v)
    fmt.Printf("%v\n", v) // prints {1}
}

在这种情况下,代码的行为符合我的预期。这v变量在main()函数不受变量变化的影响test2()。那么为什么地图不同呢?


你是对的,当你将某些东西传递给函数时,就会创建一个副本。但映射是底层数据结构的某种描述符。因此,当您将映射值传递给函数时,只会复制描述符,该描述符将表示/指向存储映射数据(条目)的相同数据结构。

这意味着如果函数对映射的条目进行任何修改(添加、删除、修改条目),则会从调用者处观察到。

Read Go 博客:Go 地图的实际应用了解详情。

请注意,这同样适用于slices and channels也;一般来说,您可以使用内置创建的类型make()功能。这就是为什么零值这些类型中的一个是nil,因为这些类型的值需要一些额外的初始化,这是在调用时完成的make().

在您的另一个示例中,您正在使用struct值,它们不是描述符。当你通过一个struct值到另一个函数,该函数创建结构体值的完整副本(复制其所有字段的值),当在函数内部修改时,它不会对原始值产生任何影响,因为副本的内存将被修改 -这是独特的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么一个函数中的映射值会受到另一函数中映射条目的影响? 的相关文章