《Go语音圣经(中文版)》笔记(10)
Contents
#《Go 语音圣经(中文版)》
#复合数据类型
#Map
哈希表是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。
在Go语言中,一个map就是一个哈希表的引用,map类型可以写为map[K]V,其中K和V分别对应key和value,map中所有的key都有相同的类型,所有的value也有着相同的类型,但是key和value之间可以是不同的数据类型。其中K对应的key必须是支持==比较运算符的数据类型,所以map可以通过测试key是否相等来判断是否已经存在。
内置的make函数可以创建一个map:
1 | ages := make(map[string]int) |
也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value:
1 | ages := map[string]int{ |
1 | // ------------------------------------------- |
map[string]int{}可以用来创建空的map的表达式。
使用内置的delete函数可以删除元素:
1 | delete(ages, "alice") |
如果一个查找失败将返回value类型对应的零值。
x += y和x++等简短赋值语法也可以用在map上。
map中的元素并不是一个变量,因此我们不能对map的元素进行取址操作,原因是map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效。
map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。
map类型的零值是nil,也就是没有引用任何哈希表。
1 | var ages map[string]int |
map上的大部分操作,包括查找、删除、len和range循环都可以安全工作在nil值的map上,它们的行为和一个空的map类似。但是向一个nil值的map存入元素将导致一个panic异常:
1 | ages["carol"] = 21 // panic: assignment to entry in nil map |
在向map存数据前必须先创建map。
通过key作为索引下标来访问map将产生一个value。如果key在map中是存在的,那么将得到与key对应的value;如果key不存在,那么将得到value对应类型的零值。
第二个返回值用来确定对应的元素是否真的是在map之中:
1 | age, ok := ages["bob"] |
在这种场景下,map的下标语法将产生两个值,第二个是一个布尔值,用于报告元素是否真的存在。布尔变量一般命名为ok,特别适合马上用于if条件判断部分。
map之间不能进行相等比较,唯一的例外是和nil进行比较。
有时候我们需要一个map或set的key是slice类型,但是map的key必须是可比较的类型,但是slice并不满足这个条件。不过,我们可以通过两个步骤绕过这个限制。第一步,定义一个辅助函数k,将slice转为map对应的string类型的key,确保只有x和y相等时k(x) == k(y)才成立。然后创建一个key为string类型的map,在每次对map操作时先用k辅助函数将slice转化为string类型。
map的value类型也可以是一个聚合类型,比如是一个map或slice。
1 | // ------------------------------------------- |
1 | [11:05:51] onns@Onns ~/Documents/code/go/go-bible/ch4 $ go run 4.4.go |