总而言之:
为什么它们是无序的?
实际值存储在内存中的什么位置?
在深入研究运行时包后,我发现底层地图结构如下:
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
buckets- 是存储桶数组,其中索引是键哈希的低位位,其中存储桶是:
// A bucket for a Go map.
type bmap struct {
// tophash generally contains the top byte of the hash value
// for each key in this bucket. If tophash[0] < minTopHash,
// tophash[0] is a bucket evacuation state instead.
tophash [bucketCnt]uint8
// Followed by bucketCnt keys and then bucketCnt elems.
// NOTE: packing all the keys together and then all the elems together makes the
// code a bit more complicated than alternating key/elem/key/elem/... but it allows
// us to eliminate padding which would be needed for, e.g., map[int64]int8.
// Followed by an overflow pointer.
}
..好吧,它只是一个数组,uint8其中每个项目都是密钥散列的第一个字节。键值对存储为key/key value/value(每个桶八对)。但具体在哪里呢?考虑到映射可能包含(几乎)任何类型的值。应该有某种指针放置在存储值数组的内存中,但bmap没有此类信息。
由于密钥的哈希值位于存储桶内的有序数组中,为什么每次我循环遍历地图时它的顺序都不同?
米琪卡哇伊
相关分类