这是我的代码:
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(使用前将#替换为@)