Модуль
1map← вы здесь2Массивы3Слайсы4Структуры
Урок 3~12 минут

map

Что такое map

map — хеш-таблица: хранит пары ключ→значение. Ключом может быть любой comparable тип (числа, строки, структуры без слайсов). Значением — что угодно.


Создание

go
// make — предпочтительный способ
ages := make(map[string]int)
 
// Литерал с начальными значениями
capitals := map[string]string{
    "Россия":  "Москва",
    "Германия": "Берлин",
    "Япония":  "Токио",
}
 
// nil-map — нельзя писать!
var m map[string]int
m["key"] = 1 // panic: assignment to entry in nil map

Запись и чтение

go
ages := make(map[string]int)
 
// Запись
ages["Алиса"] = 30
ages["Боб"] = 25
 
// Чтение
fmt.Println(ages["Алиса"]) // 30
fmt.Println(ages["Карл"])  // 0 — ключа нет, но паники нет

Comma-ok паттерн

Чтобы отличить «ключ со значением 0» от «ключа нет»:

go
age, ok := ages["Карл"]
if !ok {
    fmt.Println("Карл не найден")
} else {
    fmt.Printf("Карлу %d лет\n", age)
}

Короткий вариант:

go
if age, ok := ages["Алиса"]; ok {
    fmt.Printf("Алисе %d лет\n", age)
}

Удаление

go
delete(ages, "Боб")
fmt.Println(len(ages)) // уменьшился на 1

delete безопасен — не паникует если ключа нет.


Итерация

go
for name, age := range ages {
    fmt.Printf("%s: %d\n", name, age)
}

Порядок не гарантирован — каждый раз разный. Для сортировки:

go
keys := make([]string, 0, len(ages))
for k := range ages {
    keys = append(keys, k)
}
sort.Strings(keys)
 
for _, k := range keys {
    fmt.Printf("%s: %d\n", k, ages[k])
}

Вложенные map

go
graph := map[string][]string{
    "A": {"B", "C"},
    "B": {"D"},
    "C": {"D", "E"},
}
fmt.Println(graph["A"]) // [B C]

Или map of maps:

go
matrix := map[int]map[int]int{}
matrix[0] = map[int]int{0: 1, 1: 2}
matrix[1] = map[int]int{0: 3, 1: 4}

Частые паттерны

Счётчик:

go
words := strings.Fields("go is great go is fast")
count := make(map[string]int)
for _, w := range words {
    count[w]++
}
// count["go"] = 2, count["is"] = 2, ...

Множество (set):

go
seen := make(map[string]struct{})
seen["alice"] = struct{}{}
 
if _, ok := seen["alice"]; ok {
    fmt.Println("уже видели")
}

struct{} занимает 0 байт — идеально для множеств.


Конкурентный доступ

map не потокобезопасна. Одновременное чтение+запись из разных горутин вызовет панику. Решения:

go
// sync.Mutex
var mu sync.Mutex
mu.Lock()
m[key] = value
mu.Unlock()
 
// sync.Map — для read-heavy сценариев
var sm sync.Map
sm.Store("key", 42)
v, _ := sm.Load("key")
Всегда проверяй второй return при чтении из map: v, ok := m[key]. Если ключа нет — вернётся нулевое значение, и ты не узнаешь об этом без ok.
КлючЗначение
"alice"30
"bob"25
"carol"28
Живой код:
m := map[string]int{ "alice": 30, "bob": 25, "carol": 28, } // Добавить / обновить m["diana"] = 22 // Удалить delete(m, "bob") // Найти (comma-ok) val, ok := m["alice"] // val=30, ok=true
🎯
Миссия 1 из 4
Как создать map с ключами string и значениями int?