为了账号安全,请及时绑定邮箱和手机立即绑定

地图类型是引用类型。var m map[string]int 不指向已初始化的映射。这是什么意思?

地图类型是引用类型。var m map[string]int 不指向已初始化的映射。这是什么意思?

Go
30秒到达战场 2022-01-17 10:26:01
我在 golang 博客上读过:https ://blog.golang.org/go-maps-in-action:var m map[string]int映射类型是引用类型,如指针或切片,所以上面 m 的值为 nil;它不指向初始化的地图。读取时,nil 映射的行为类似于空映射,但尝试写入 nil 映射会导致运行时恐慌;不要那样做。要初始化地图,请使用内置的 make 函数:m = make(map[string]int)make 函数分配并初始化一个哈希映射数据结构,并返回一个指向它的映射值。我很难理解其中的某些部分:做什么var m map[string]int?为什么我需要写m = make(map[string]int)但不需要i = make(int)
查看完整描述

3 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

var m map[string]int 有什么作用?

它告诉编译器这m是一个类型的变量map[string]int,并将 map[string] int 类型的“零值”分配给m(这就是为什么 m 为 nil,因为 nil 是任何映射的零值)。

为什么我需要写 m = make(map[string]int) 而不是 i = make(int)

你不需要。您也可以像这样创建一个初始化的地图:

m = map[string]int{}

这完全一样。

map 和 int 之间的区别是: nil map 非常好。例如len(),一个 nil 映射有效并且为 0。你不能用一个 nil 映射做的唯一事情是存储键值对。如果你想这样做,你必须准备/初始化地图。Go 中的这种准备/初始化是通过内置函数make(或如上所示的文字映射)完成的。整数不需要此初始化过程。由于没有零整数,因此此初始化将是总噪声。

请注意,您没有初始化变量 m:变量m是字符串到整数的映射,无论是否初始化。Likei是整数的变量。现在 int 可以直接使用,而 map 需要多一步,因为语言就是这样工作的。


查看完整回答
反对 回复 2022-01-17
?
狐的传说

TA贡献1804条经验 获得超3个赞

var m map[string]int 有什么作用?


您可以将其视为具有 nil 值的指针,它尚未指向任何内容,但能够指向具体值。


为什么我需要写 m = make(map[string]int) 而不是 i = make(int)


https://golang.org/doc/effective_go.html#allocation_make


回到分配。内置函数 make(T, args) 的用途与 new(T) 不同。它只创建切片、映射和通道,并返回 T 类型(不是 *T)的初始化(非归零)值。区别的原因是这三种类型在幕后代表了对必须在使用前初始化的数据结构的引用。例如,切片是一个包含指向数据(在数组内部)、长度和容量的指针的三项描述符,在这些项被初始化之前,切片为 nil。对于切片、映射和通道,make 初始化内部数据结构并准备值以供使用。例如,


make([]int, 10, 100)

分配一个 100 个整数的数组,然后创建一个长度为 10、容量为 100 的切片结构,指向数组的前 10 个元素。(创建切片时,可以省略容量;有关更多信息,请参阅切片部分。)相反,new([]int) 返回一个指向新分配的零切片结构的指针,即指向零切片值。


这些示例说明了 new 和 make 之间的区别。


var p *[]int = new([]int)       // allocates slice structure; *p == nil; rarely useful

var v  []int = make([]int, 100) // the slice v now refers to a new array of 100 ints


// Unnecessarily complex:

var p *[]int = new([]int)

*p = make([]int, 100, 100)


// Idiomatic:

v := make([]int, 100)

请记住,make 仅适用于映射、切片和通道,并且不返回指针。要获得显式指针,请使用 new 分配或显式获取变量的地址。


查看完整回答
反对 回复 2022-01-17
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

所有字都具有相同的长度,即32 位(4 字节)64 位(8 字节),具体取决于处理器和操作系统。它们由它们的内存地址标识(表示为十六进制数)。

所有原始类型的变量,如intfloatboolstring ... 都是value types,它们直接指向内存中包含的值。像数组和结构这样的复合类型也是值类型。当将=值类型的值分配给另一个变量时:j = i,原始值的副本i会在内存中生成。

通常需要几个词的更复杂的数据被视为引用类型。引用类型变量r1包含存储值的内存位置的地址(一个数字)r1(或至少它的第一个字):

//img1.sycdn.imooc.com//61e4d3e70001f61d03920074.jpg

对于分配时r2 = r1的引用类型,仅复制引用(地址)而不复制值!!。如果 r1 的值被修改,该值的所有引用(如 r1 和 r2)都将被反映。

在 Go 中,指针是引用类型,以及切片、映射和通道。引用的变量存储在堆中,这是垃圾收集的。

鉴于上述陈述,文章为何指出:

要初始化地图,请使用内置的 make 函数。

make 函数分配并初始化一个哈希映射数据结构,并返回一个指向它的映射值。这意味着你可以写入它,比较

var m map[string]int

这是可读的,产生一个nil映射,但尝试写入一个 nil 映射将导致运行时恐慌。这就是为什么用 初始化地图很重要的原因make

m = make(map[string]int)


查看完整回答
反对 回复 2022-01-17
  • 3 回答
  • 0 关注
  • 165 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信