go语言读书笔记-action系列(映射)

对于习惯了map这种表述方式的我,现在看来还是go中使用映射这个词,表达这一结构感觉更加精准点。

映射内部实现方式

映射的内部是无序的,因为其使用了散列表。
image_1d4rk5af2rkt1taiego1ied6jv9.png-156.1kB

映射的散列结构包含一组桶,所有的操作都要先选择一个桶。把操作映射时指定的键传递给映射的散列函数就可以选中对应的桶。
go语言生成散列键的过程如下:

  1. 这些字符串会转换为一个数值(散列值)。
  2. 这个数值落在映射已有桶的序号范围内表示一个可以用于存储的桶的序号。
  3. 最后这个数值被用来选择桶,用于存储或者查找指定的键值对。

在此需要强调的是,散列值的低位用来选择桶,高位用来区分不同的项。
对于桶的内部实现,感觉action中解释的并不是很好,尤其这个散列值高位的作用,解释感觉很难理解。
桶的内部实现使用两个数据结构实现。第一个是数组,内部存储的是用于选择桶的散列键的高位值(在对key/value对增删查的时候,先比较key的hash值高八位是否相等,然后再比较具体的key值,主要用来帮助区分寻找对应的key,不用每次都对key做全等判断)。第二个数据结构是一个字节数组,用于存储键值对。该字节数组存储了这个桶里所有的键,之后依次存储了这个桶里所有的值。

映射的扩容

action没有提到这一点,但是我觉得应该去探索下。
在桶中插入元素时,当桶填满后,将通过overflow指针来mallocgc一个新的bucket出来形成链表。
随着元素的增长,在桶链中寻找特定的key会变得效率低下,所以再插入的元素个数/桶达到阙值时(貌似设置为6.5),map会扩容,创建新的桶数组,长度为之前长度的两倍。