Словари (map)

map — словарь Go: создание, доступ, удаление и важная идиома проверки ok.

map — хеш-таблица: коллекция пар «ключ — значение» с быстрым доступом по ключу. Аналог dict в Python и объекта-словаря в JavaScript.

Создание и заполнение

Тип записывается как map[КлючТип]ЗначениеТип. Создают map литералом или через make. Внимание: nil-map (объявленная через var без инициализации) доступна на чтение, но запись в неё вызовет панику — поэтому используйте make или литерал.

package main

import "fmt"

func main() {
    ages := map[string]int{
        "Аня":  30,
        "Борис": 25,
    }
    ages["Вера"] = 28 // добавление
    fmt.Println(ages["Аня"])
    fmt.Println(len(ages))
}

Вывод:

30
3

Идиома проверки ok

Если запросить отсутствующий ключ, map вернёт нулевое значение типа — и вы не отличите «ключа нет» от «значение равно нулю». Поэтому существует форма с двумя результатами: значение и булев флаг наличия.

package main

import "fmt"

func main() {
    stock := map[string]int{"яблоки": 0}

    n := stock["груши"] // 0, но ключа нет
    fmt.Println(n)

    if v, ok := stock["яблоки"]; ok {
        fmt.Println("яблоки есть, остаток:", v)
    }
    if _, ok := stock["груши"]; !ok {
        fmt.Println("груш нет в каталоге")
    }
}

Вывод:

0
яблоки есть, остаток: 0
груш нет в каталоге

Эта идиома v, ok := m[key] — стандартный способ проверить наличие ключа. Запомните её: она встречается в Go-коде постоянно.

Удаление

Встроенная функция delete убирает ключ. Если ключа не было — ничего не произойдёт, ошибки не будет.

package main

import "fmt"

func main() {
    m := map[string]int{"a": 1, "b": 2}
    delete(m, "a")
    fmt.Println(m, len(m))
}

Вывод:

map[b:2] 1

Перебор и порядок

map перебирают через for range. Важная особенность: порядок обхода не определён и меняется от запуска к запуску — Go намеренно рандомизирует его, чтобы код не полагался на порядок. Нужен порядок — соберите ключи в срез и отсортируйте.

for key, value := range ages {
    fmt.Println(key, value)
}

Итог

  • map создают через литерал или make; запись в nil-map паникует.
  • Идиома v, ok := m[key] отличает отсутствие ключа от нулевого значения.
  • delete убирает ключ; порядок обхода map не определён.
Проверьте себя
1. Как идиоматично проверить, есть ли ключ в map?
Aif m[key] != nil
Bv, ok := m[key] и проверить ok
Clen(m[key]) > 0
Dm.has(key)
2. Что вернёт обращение к отсутствующему ключу map[string]int?
Anil
Bпанику
Cнулевое значение типа (0)
Dошибку компиляции
3. Каков порядок обхода map через for range?
AПо возрастанию ключей
BВ порядке добавления
CНе определён и рандомизирован
DПо убыванию значений
Поддержать проект