Мапы¶
TL;DR¶
map[K]V— hashmap, доступ O(1) amortized.v, ok := m[k]— comma-ok idiom для проверки.- Итерация в случайном порядке.
- nil map можно читать (вернёт zero value), писать в неё — panic.
- Запись из нескольких горутин одновременно — fatal error.
Создание¶
m := map[string]int{"a": 1, "b": 2}
m := make(map[string]int)
m := make(map[string]int, 100) // подсказка по capacity
var m map[string]int // nil map, читать можно, писать нельзя
Comma-ok¶
Без ok нельзя отличить «нет ключа» от «значение == zero».
Конкурентность¶
Map в Go не thread-safe. Несколько горутин одновременно пишут → fatal error: concurrent map writes.
Варианты:
// 1. Mutex
var m = struct{
sync.RWMutex
data map[string]int
}{data: map[string]int{}}
m.Lock()
m.data["a"] = 1
m.Unlock()
// 2. sync.Map — но только если ключи редко меняются и читателей сильно больше
var sm sync.Map
sm.Store("a", 1)
v, ok := sm.Load("a")
Когда sync.Map лучше: read-mostly, write-rare. В общем случае
map + Mutex быстрее.
Гочча — нельзя взять адрес¶
Map может быть переаллоцирован при росте → адреса нестабильны.
Гочча — итерация в случайном порядке¶
Это сделано намеренно, чтобы код не полагался на порядок. Если порядок нужен — собери ключи в slice, отсортируй, итерируй по slice.
📖 Связанные задачи: must-solve-100 → C-005, C-011.
Полезные материалы¶
📺 Видео
- Map в Go под капотом, часть 1 (RU) — bucket'ы, hashing, итерация в случайном порядке.
- Map в Go под капотом, часть 2 (RU) — эвакуация (incremental rehash), concurrent writes, panic.
📚 Статьи
- sync.Map — как устроена внутри (RU) —
read map + dirty map, когда
sync.Mapбыстрееmap+Mutex, а когда нет.
Подробные карточки вопросов «что спросят про мапы» — в sprint-1/theory-cards.md.