Го карты под капотом - PullRequest
       34

Го карты под капотом

4 голосов
/ 11 декабря 2019

После прочтения блога Дейва Чейни о картах Го мне все еще мало что неясно.

TLDR:

  • Почему они неупорядочены?
  • Где фактические значения хранятся в памяти?

После поиска в пакете runtime я обнаружил, что основная картаструктура выглядит следующим образом:

// 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 не имеет такой информации.

И, поскольку хэши ключей расположены в упорядоченном массиве внутри сегмента, то почему этот порядок отличаетсякаждый раз, когда я перебираю карту?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...