我正在跟随之旅,有些事困扰着我。
使用前必须使用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
创建地图?我在这里错过了什么吗?
答案 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
,然后制作副本并在以后初始化基础数据,你将拥有两个完全独立的数据结构,这通常不是你想要的。