Внутренняя реализация map в Go

Go map — хеш-таблица с открытой адресацией и бакетами по 8 пар ключ-значение.

map[K]V
├── hmap (заголовок)
│   ├── count       — число элементов
│   ├── B           — log2(количество бакетов)
│   ├── buckets     — указатель на массив бакетов
│   └── oldbuckets  — указатель при росте (rehash)
└── bmap (бакет, 8 ячеек)
    ├── tophash[8]  — верхние 8 бит хеша каждого ключа
    ├── keys[8]
    └── values[8]

tophash позволяет быстро отсеять несовпадения без полного сравнения ключей.

// Нулевое значение при отсутствии ключа
m := map[string]int{"a": 1}
v := m["missing"] // 0, не паника

// Проверка наличия
v, ok := m["missing"]
if !ok { fmt.Println("нет ключа") }

// Удаление
delete(m, "a")

// Итерация — порядок не гарантирован
for k, v := range m { fmt.Println(k, v) }

Go намеренно рандомизирует порядок обхода map — защита от кода, случайно зависящего от порядка. Для детерминированного порядка — сортируй ключи:

keys := make([]string, 0, len(m))
for k := range m { keys = append(keys, k) }
sort.Strings(keys)
for _, k := range keys { fmt.Println(k, m[k]) }

Стандартная map не потокобезопасна. Варианты:

// sync.Mutex вручную
var mu sync.Mutex
mu.Lock()
m[key] = value
mu.Unlock()

// sync.Map — встроенная потокобезопасная реализация
var sm sync.Map
sm.Store("key", 42)
v, ok := sm.Load("key")

sync.Map оптимизирована для случая «много чтений, редкие записи».


ЗаданиеСложность
1Упражнение 1easy
2Упражнение 2easy
3Упражнение 3medium