8.0 Map
map 是一种特殊的数据结构:一种元素对(pair)的无序集合,pair 的一个元素是 key,对应的另一个元素是 value,所以这个结构也称为关联数组或字典。这是一种快速寻找值的理想结构:给定 key,对应的 value 可以迅速定位。
map 这种数据结构在其他编程语言中也称为字典(Python)、hash 和 HashTable 等。
8.1 声明、初始化和 make
8.1.1 概念
map 是引用类型,可以使用如下声明:
[keytype]valuetype
在声明的时候不需要知道 map 的长度,map 是可以动态增长的。
未初始化的 map 的值是 nil。
Key()Hash()
value 可以是任意类型的;通过使用空接口类型(详见第 11.9 节),我们可以存储任意值,但是使用这种类型作为值时需要先做一次类型断言(详见第 11.3 节)。
map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了多少数据。通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题。
map 也可以用函数作为自己的值,这样就可以用来做分支结构(详见第 5 章):key 用来选择要执行的函数。
map1[key1]
map1[key1] = val1
v := map1[key1]
len(map1)
示例 8.1 make_maps.go
输出结果:
map literals{key1: val1, key2: val2}
map 是 引用类型 的: 内存用 make 方法来分配。
var map1 = make(map[keytype]valuetype)
map1 := make(map[keytype]valuetype)
mapCreated := make(map[string]float32)
mapCreated := map[string]float32{}
mapAssigned 也是 mapList 的引用,对 mapAssigned 的修改也会影响到 mapLit 的值。
不要使用 new,永远用 make 来构造 map
注意 如果你错误的使用 new() 分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址:
mapCreated["key1"] = 4.5
func() int
示例 8.2 map_func.go
map[1:0x10903be0 5:0x10903ba0 2:0x10903bc0]
8.1.2 map 容量
capacitymake(map[keytype]valuetype, cap)
当 map 增长到容量上限的时候,如果再增加新的 key-value 对,map 的大小会自动加 1。所以出于性能的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明。
这里有一个 map 的具体例子,即将音阶和对应的音频映射起来:
8.1.3 用切片作为 map 的值
[]int
这里有一些定义这种 map 的例子: