在Go中,地图是通过值传递还是通过引用传递?


89

Go中的地图是否通过值或引用传递?

始终可以将函数定义为以下形式,但这是一个过大的杀伤力吗?

func foo(dat *map[string]interface{}) {...}

相同的返回值问题。我应该返回指向地图的指针还是将地图作为值返回?

这样做的目的当然是避免不必要的数据复制。


4
blog.golang.org/go-maps-in-action:地图类型是引用类型,例如指针或切片,因此上述m的值为nil;它没有指向初始化的地图。读取时,nil映射的行为类似于空映射,但是尝试写入nil映射将导致运行时恐慌。不要那样做。要初始化地图,请使用内置的make函数
mh-cbon

2
一切都在围棋是按值传递。一些值恰好是指针或包含指针的结构。(*map在某些情况下,如果您需要在某个地址上重新分配地图值,则可能需要a )
JimB

mh-cbon,Go中没有引用类型。
伊南克·古姆斯

@ mh-cbon我不是在谈论引用类型。我在问一个映射是否通过引用传递,这等效于询问该映射的地址是作为参数传递还是作为映射的“副本”(按值传递)。
chmike

1
@ mh-cbon确实,映射是指向hmap的指针。
伊南克·古姆斯

Answers:


79

在此线程中,您将找到答案:

Golang:使用地图参考来访问地图

您不需要在地图上使用指针。

映射类型是引用类型,例如指针或切片[1]

如果需要更改会话,可以使用一个指针:

map[string]*Session

https://blog.golang.org/go-maps-in-action


15
为避免任何麻烦,请注意,映射仅在初始化后通过引用传递,并且在函数内部重新初始化时,原始引用将不会更新。这是一个说明性的游乐场示例:play.golang.org/p/Q6vrAmmJWR6 或Dave Cheny的完整文章dave.cheney.net/2017/04/29/the-is-no-pass-by-by-reference-in-go
Sindre Myren '18

18

以下是一些地方如果地图不是引用变量,它是什么?戴夫·切尼(Dave Cheney):

映射值是指向runtime.hmap结构的指针。

和结论:

结论

映射与通道一样,但与切片不同,只是指向运行时类型的指针。正如您在上面看到的,地图只是指向runtime.hmap 结构的指针。

映射具有与Go程序中任何其他指针值相同的指针语义。除了编译器将Map语法重写为调用in中的函数外,没有其他魔术runtime/hmap.go

关于map语法的历史/解释的有趣一点:

如果地图是指针,那不是*map[key]value吗?

很好的问题是,如果映射是指针值,那么表达式为什么make(map[int]int)返回类型为的值 map[int]int。它不应该返回*map[int]int吗?伊恩·泰勒(Ian Taylor) 最近在golang-nuts线程1中回答了这个问题

在早期,我们所谓的地图现在是作为指针编写的,因此您写道*map[int]int。当我们意识到没有人map没有写作的时候,我们便放弃了*map

可以说,将类型从from重命名*map[int]intmap[int]int,尽管由于类型看起来不像指针而令人困惑,但与无法取消引用的指针形状值相比,混乱程度较小。


1

否。默认情况下,地图为参考。

    package main

    import "fmt"

    func mapToAnotherFunction(m map[string]int) {
        m["hello"] = 3
        m["world"] = 4
        m["new_word"] = 5
    }

    // func mapToAnotherFunctionAsRef(m *map[string]int) {
    // m["hello"] = 30
    // m["world"] = 40
    // m["2ndFunction"] = 5
    // }

    func main() {
        m := make(map[string]int)
        m["hello"] = 1
        m["world"] = 2

        // Initial State
        for key, val := range m {
            fmt.Println(key, "=>", val)
        }

        fmt.Println("-----------------------")

        mapToAnotherFunction(m)
        // After Passing to the function as a pointer
        for key, val := range m {
            fmt.Println(key, "=>", val)
        }

        // Try Un Commenting This Line
        fmt.Println("-----------------------")

        // mapToAnotherFunctionAsRef(&m)
        // // After Passing to the function as a pointer
        // for key, val := range m {
        //  fmt.Println(key, "=>", val)
        // }

        // Outputs
        // hello => 1
        // world => 2
        // -----------------------
        // hello => 3
        // world => 4
        // new_word => 5
        // -----------------------

    }

来自Golang博客-

映射类型是引用类型,例如指针或切片,因此上面的m的值为nil;它没有指向初始化的地图。读取时,nil映射的行为类似于空映射,但是尝试写入nil映射将导致运行时恐慌。不要那样做。要初始化地图,请使用内置的make函数:

// Ex of make function
m = make(map[string]int)

代码段链接玩。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.