地图是通过价值或Go中的参考传递的吗?

chm*_*ike 57 go

Go中的值是通过值传递还是引用?

始终可以将函数定义如下,但这是否过度?

func foo(dat *map[string]interface{}) {...}
Run Code Online (Sandbox Code Playgroud)

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

目的当然是避免不必要的数据复制.

Bor*_*éec 58

在这个帖子中你会找到你的答案:

Golang:使用其引用访问地图

您不需要使用带有地图的指针.

地图类型是引用类型,如指针或切片[1]

如果您需要更改Session,可以使用指针:

map[string]*Session
Run Code Online (Sandbox Code Playgroud)

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

  • 为避免任何pitfals,请注意,只有_initialized_才会通过引用传递映射,并且在函数内重新初始化时,原始的_reference_将不会更新.这是一个说明性的游乐场示例:https://play.golang.org/p/Q6vrAmmJWR6或Dave Cheny的完整文章https://dave.cheney.net/2017/04/29/there-is-no-pass逐参考功能于去 (8认同)
  • 就我个人而言,我认为(顺便提及)“切片是引用类型”是有误导性的,因为它们实际上并非如此?如果您将切片按值传递给函数,然后多次追加到它,则不能保证调用者的该切片的副本会被更新 - 相反,被调用的函数需要传回切片的新值。这是因为,如果切片重新分配,您将获得该切片的新值(因此“a =append(a, v)”而不仅仅是“append(a, v)”)一旦映射没有这种语义,创建地图后,可以对其进行更新,而不会产生新的地图值。 (5认同)
  • 错误 - 无论是否为零,地图总是以相同的方式传递。此外,如果不将指针传递给映射并使用解引用赋值,则无法重新初始化映射。相同的链接代码证明了后者,而前者可以通过不初始化地图轻松证明。正如 19 个赞成票所示,Go 很容易出错。 (3认同)

Aka*_*all 10

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

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

和结论:

结论

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

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

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

如果地图是指针,它们是否应该是* map [key] value?

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

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

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


ala*_*min 7

No. Maps are reference by default.

    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
        // -----------------------

    }
Run Code Online (Sandbox Code Playgroud)

From Golang Blog-

Map 类型是引用类型,比如指针或切片,所以上面的 m 的值是 nil;它不指向初始化的映射。nil map 在读取时表现得像一个空 map,但尝试写入 nil map 会导致运行时恐慌;不要那样做。要初始化地图,请使用内置的 make 函数:

// Ex of make function
m = make(map[string]int)
Run Code Online (Sandbox Code Playgroud)

代码片段链接玩它。

  • 它们不是引用类型(尽管它们是间接类型)。如果分配给映射值,则会破坏它与其他变量的关系。Go 没有引用类型,一切都是值。您可以使用 func mapToAnotherFunction(m map[string]int) { m = nil }` 来演示这一点,它不会清空映射,只是以本地方式覆盖其值。 (2认同)