- 为什么它们无序?
因为这为运行时提供了 更大的自由
以实现映射类型。尽管我们知道Go的(当前)实现是一个哈希图,但语言规范允许使用任何地图实现(例如哈希图,树图等)。也不必记住顺序,这使运行时可以更有效地完成工作,减少使用记忆。
Adrian的评论很好地总结了很少需要订单,而始终保持订单是浪费。当您确实需要订购时,可以使用提供订购的数据结构。
而且由于键的哈希值位于存储桶中的有序数组中,为什么每次我遍历地图时它的顺序都不同?
Go的作者有意使地图的迭代顺序随机化(因此我们凡人不会依赖固定的顺序)。
- 实际值存储在哪里?
“ where”由指定
hmap.buckets。这是一个指针值,它指向内存中的一个数组,该数组保存存储桶。
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
因此,
hmap.buckets指向存储桶的连续内存段。存储桶由进行“建模”
bmap,但这不是其实际的内存布局。存储桶的开头是一个存储桶(
tophash [bucketCnt]uint8)中存储键的最高哈希字节的数组,该数组
后面
bucketCnt是存储桶的键,然后
bucketCnt是存储桶的值。最后,有一个溢出指针。
将存储桶想像成这种 概念性 类型,它可以“可视化”键和值在内存中的位置:
type conceptualBucket struct { tophash [bucketCnt]uint8 keys [bucketCnt]keyType values [bucketCnt]valueType overflowPtr uintptr}注意:
bucketCnt是一个编译时间常数,为
8,它是存储桶可以容纳的密钥/元素对的最大数量。
当然,这种“图片”是不准确的,但是它给出了存储键和值的位置/方式的想法。



