2022-12-29_23_58-go学习笔记(13)map
go语言针对数据映射的情况原生提供了map数据类型,可以这样定义一个map:map[键类型]值类型。
map的定义声明
直接用var定义的map是nil的map,其值为nil。对nil的map进行读操作总是会返回对应的零值,进行写操作会导致panic。
1 | var m map[string]int |
所以如果想要使用map,就不能使用值为nil的map。
可以通过:=
快速创建一个字面量为空的map,字面量为空的map不是nil的map。可能有些绕,把它类比成指针就比较好理解了,nil的map就相当于一个空指针,字面量为空的map就相当于这个指针指向了一个空白的区域。
1 | m:=map[string]int{} |
如果map在定义时已经有现成的键值对数据,也可以直接在定义时用非空的字面量来创建map。最后一个键值对后面要么直接跟}
收尾,要么与前面一致用逗号分隔然后另起一行用}
收尾。
1 | m := map[string]int{ |
输出:
1 | 1 |
可以用make
来创建map,如果预先知道map大致容量也可以在make时设置初始容量,减少扩容次数。
1 | var m map[string]int |
输出:
1 | 1 |
map
和slice
有很多相似的地方:
map
在添加键值对时会自动扩容- 在知道有多少键值对时,可以用
make
指定map
的初始容量 - 通过
len
函数可以获取map
中键值对个数 map
的零值是nil
- 两个
map
之间不能比较。
map的键必须是可比较的类型,我们不能用slice或map等不可比较的类型作为map的键。
如何判断键是否存在
map对不存在的键会返回其对应值的零值,这样我们就不能通过其返回值来判断相应的键是否存在。
在获取map中键对应的值的时候,可以通过其第二个返回值来判断。
1 | m := map[string]int{ |
输出:
1 | 0 false |
第二个返回值为false就说明键不存在了。
删除map中的键值对
通过go语言内置的delete函数可以删除键值对。
1 | m := map[string]int{ |
输出:
1 | 0 false |
将map当成set来用
很多语言中有集合类型,但go语言中没有。如果不需要集合交并运算,只需要去重和判断数据存不存在的话,我们可以把map当成set来用。
1 | // 假如我们要用set对一组数据去重,得到不重复数据的个数 |
输出:
1 | 7 |
也可以用空结构体struct{}
替换bool
实现set,用空结构体的好处是空结构体不占内存,适用于数据量很大的情况。缺点是写起来比较麻烦。
1 | nums := []int{ |
输出:
1 | 7 |
map键值对中结构体数据的更新
如果有其他语言经验的,如用过c++标准库中的map,很可能会想当然地认为可以直接修改键值对的值。
在c++中可以像下面这样:
1 | struct point |
输出:
1 | 4 1 |
可以看到mp["a"]
的值被改了。
但在go语言中不能这样做,会直接报错。
只能用新的值去覆盖原来的值:
1 | type Point struct { |
输出:
1 | {4 1} |