通过引用传递值时的映射奇怪变异(Golang)

时间:2017-06-11 17:34:09

标签: function go parameter-passing mutability

第一种情况中,我按地图传递地图: 包主要

%2

输出是静音地图:

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)
}

我的期望如下:

  • 当通过值图时静音
  • 当通过参考地图时,像第二情况一样静音。 但是,在第一个案例中,地图已静音,但顺序相反(与第二案例相比)。

为什么会这样?

1 个答案:

答案 0 :(得分:3)

在Go中没有通过引用传递的东西。无论何时传递任何东西(指针,切片标题,映射),它总是按值传递。问题是究竟是通过值传递的是什么(即该类型的实际value是什么)。

当你传递一张地图时,你会将指针的副本传递给它的标题,该标题包含一个指向存储桶的设置指针,就像在HashTable的实现中一样。 https://github.com/golang/go/blob/master/src/runtime/hashmap.go#L106

因此,将指针传递给地图很少有意义,因为复制地图标题指针的操作非常便宜。

现在为什么顺序不同,这仅仅是由于地图的内部实现,键的范围以随机的方式发生。这只是一个实现细节。

编辑:

正如@icza正确指出的那样,传递地图实际上是将指针的副本传递给地图标题,而不是地图标题本身。对不起困惑