在任何事情之前制作地图

时间:2014-08-23 13:47:09

标签: go maps

我正在跟随之旅,有些事困扰着我。

  

使用前必须使用make(非新)创建地图

足够公平:

map = make(map[int]Cats)

然而,下一张幻灯片显示了不同的内容:

   var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}

此幻灯片展示了在创建地图时如何忽略make

为什么导游说在使用之前必须使用make创建地图?我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:4)

实际上,使用make来创建地图的唯一原因是预先分配特定数量的值,就像切片一样(除了你不能在地图上设置上限)

m := map[int]Cats{}
s := []Cats{}
//is the same as
m := make(map[int]Cats)
s := make([]Cats, 0, 0)

但是,如果您知道地图中的项目数量至少为X,则可以执行以下操作:

m := make(map[int]Cats, 100)// this will speed things up initially

同时检查http://dave.cheney.net/2014/08/17/go-has-both-make-and-new-functions-what-gives

答案 1 :(得分:1)

因此,在使用地图之前,您始终需要使用make才是正确的。看起来它们不在您给出的示例中的原因是make调用是隐式发生的。因此,例如,以下两个是等效的:

m := make(map[int]string)
m[0] = "zero"
m[1] = "one"
// Equivalent to:
m := map[int]string{
    0: "zero",
    1: "one",
}

制作与新

现在,使用make vs new的原因稍微有点微妙。原因是new仅为给定类型的变量分配空间,而make实际上初始化它。

为了让您了解这种区别,想象一下我们有这样的二叉树类型:

type Tree struct {
    root *node
}

type node struct {
    val         int
    left, right *node
}

现在你可以想象,如果我们有Tree被分配和初始化并且其中有一些值,并且我们制作了Tree值的副本,那么这两个值将指向相同的基础数据,因为它们都具有root的相同值。

那么如果我们刚刚创建一个新的Tree而没有初始化它会发生什么?像t := new(Tree)var t Tree之类的东西?好吧,t.root将为零,所以如果我们复制t,两个变量都不会指向相同的基础数据,因此如果我们向Tree添加了一些元素,我们最终得到两个完全独立的Trees

Go中的地图和切片(以及其他一些)也是如此。当您复制切片变量或映射变量时,旧变量和新变量都引用相同的基础数据,就像Java或C中的数组一样。因此,如果您只使用new,然后制作副本并在以后初始化基础数据,你将拥有两个完全独立的数据结构,这通常不是你想要的。