传递值时与通过引用传递时地图的奇怪突变(Golang)
Strange mutation of map when passed value vs when passed by reference (Golang)
在第一种情况中,我按值将地图传递给:
主包
import (
"fmt"
"time"
)
func timeMap(z map[string]interface{}) {
z["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(foo)
fmt.Println(foo)
}
输出为静音贴图:
map[updated_at:2009-11-10 23:00:00 +0000 UTC Matt:42]
在第二种情况中,代码几乎相同,但通过引用传递:
package main
import (
"fmt"
"time"
)
func timeMap(z *map[string]interface{}) {
(*z)["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(&foo)
fmt.Println(foo)
}
显然,结果不同:
map[Matt:42 updated_at:2009-11-10 23:00:00 +0000 UTC]
我的期望如下:
- 当通过值映射时未静音
- 当通过参考地图时,就像在 second 情况下一样被静音。
然而,在 first 案例中地图被静音但顺序相反(与 second 案例相比)。
为什么会这样?
Go 中没有引用传递这回事。每当你传递任何东西(指针、切片 header、地图)时,它总是按值传递。问题是究竟什么是按值传递的(即类型的实际 value
是什么)。
当你传递一个映射时,你将指针的副本传递给它的header,其中包含一组指向桶的指针,如在实现中哈希表。 https://github.com/golang/go/blob/master/src/runtime/hashmap.go#L106
因此,将指针传递给地图几乎没有意义,因为复制地图 header 指针的操作非常便宜。
为什么顺序不同,这仅仅是由于地图的内部实现,以随机方式遍历键。同样,这只是一个实现细节。
编辑:
正如@icza 正确指出的那样,传递地图实际上是将 指针 的副本传递给地图 header,而不是地图 header本身。抱歉造成混淆
在第一种情况中,我按值将地图传递给: 主包
import (
"fmt"
"time"
)
func timeMap(z map[string]interface{}) {
z["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(foo)
fmt.Println(foo)
}
输出为静音贴图:
map[updated_at:2009-11-10 23:00:00 +0000 UTC Matt:42]
在第二种情况中,代码几乎相同,但通过引用传递:
package main
import (
"fmt"
"time"
)
func timeMap(z *map[string]interface{}) {
(*z)["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(&foo)
fmt.Println(foo)
}
显然,结果不同:
map[Matt:42 updated_at:2009-11-10 23:00:00 +0000 UTC]
我的期望如下:
- 当通过值映射时未静音
- 当通过参考地图时,就像在 second 情况下一样被静音。 然而,在 first 案例中地图被静音但顺序相反(与 second 案例相比)。
为什么会这样?
Go 中没有引用传递这回事。每当你传递任何东西(指针、切片 header、地图)时,它总是按值传递。问题是究竟什么是按值传递的(即类型的实际 value
是什么)。
当你传递一个映射时,你将指针的副本传递给它的header,其中包含一组指向桶的指针,如在实现中哈希表。 https://github.com/golang/go/blob/master/src/runtime/hashmap.go#L106
因此,将指针传递给地图几乎没有意义,因为复制地图 header 指针的操作非常便宜。
为什么顺序不同,这仅仅是由于地图的内部实现,以随机方式遍历键。同样,这只是一个实现细节。
编辑:
正如@icza 正确指出的那样,传递地图实际上是将 指针 的副本传递给地图 header,而不是地图 header本身。抱歉造成混淆