Map в Go
Map хранит данные, связывая ключи со значениями, и каждый элемент — это одна пара ключ:значение.
Элементы не имеют фиксированного порядка, их можно свободно изменять, а один и тот же ключ не может встречаться дважды.
Чтобы узнать, сколько элементов в map, то есть его длину, вызовите len().
Map, который не был инициализирован, имеет значение nil.
Внутри map хранит ссылки на хеш-таблицу.
Go предлагает несколько способов создать map, и следующие разделы рассматривают их.
Создание map с помощью var и :=
Для создания map с начальными значениями подходят и ключевое слово var, и оператор короткого объявления :=.
Примечание: Не ожидайте, что map сохранит порядок, который вы написали в коде. Go располагает хранимые данные по-своему, чтобы поиск значений оставался быстрым.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = map[string]string{"brand": "Ford", "model": "Mustang", "year": "1964"}
b := map[string]int{"Oslo": 1, "Bergen": 2, "Trondheim": 3, "Stavanger": 4}
fmt.Printf("a\t%v\n", a)
fmt.Printf("b\t%v\n", b)
}
Синтаксис map с var и :=
var a = map[KeyType]ValueType{key1:value1, key2:value2,...}
b := map[KeyType]ValueType{key1:value1, key2:value2,...}
Создание map с помощью функции make()
Функция make() — ещё один вариант. Она даёт вам map, который затем можно заполнять по одному ключу.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = make(map[string]string)
a["brand"] = "Ford"
a["model"] = "Mustang"
a["year"] = "1964"
b := make(map[string]int)
b["Oslo"] = 1
b["Bergen"] = 2
b["Trondheim"] = 3
b["Stavanger"] = 4
fmt.Printf("a\t%v\n", a)
fmt.Printf("b\t%v\n", b)
}
Синтаксис map с make
var a = make(map[KeyType]ValueType)
b := make(map[KeyType]ValueType)
Создание пустого map
Пустой map можно получить с помощью функции make() или объявления var без начального значения.
Примечание: Готов к использованию только первый из них, поэтому выбирать следует make(). Вариант с var равен nil, как показывает вывод, а запись в него вызывает panic во время выполнения.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = make(map[string]string)
var b map[string]string
fmt.Println(a == nil)
fmt.Println(b == nil)
}
Допустимые типы ключей
Ключ может иметь любой тип, поддерживающий оператор равенства (==), потому что Go должен уметь сравнивать ключи. К таким типам относятся:
- Булевы значения
- Числа
- Строки
- Массивы
- Указатели
- Структуры
- Интерфейсы (если динамический тип можно сравнивать на равенство)
Три типа не могут быть ключами:
- Slice
- Map
- Функции
Причина в том, что == не определён ни для одного из них.
Допустимые типы значений
У значений такого ограничения нет: map может хранить значения любого типа.
Доступ к элементам map
Чтобы прочитать элемент, укажите его ключ в квадратных скобках после имени map.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = make(map[string]string)
a["brand"] = "Ford"
a["model"] = "Mustang"
a["year"] = "1964"
fmt.Printf(a["brand"])
}
Синтаксис доступа к map
value = map_name[key]
Обновление и добавление элементов map
Присваивание значения ключу выполняет две задачи. Если ключ уже существует, его значение обновляется; если нет, добавляется новый элемент.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = make(map[string]string)
a["brand"] = "Ford"
a["model"] = "Mustang"
a["year"] = "1964"
fmt.Println(a)
a["year"] = "1970"
a["color"] = "red"
fmt.Println(a)
}
Синтаксис обновления map
map_name[key] = value
Удаление элемента из map
Вызовите функцию delete(), передав ей map и ключ, чтобы удалить этот элемент.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = make(map[string]string)
a["brand"] = "Ford"
a["model"] = "Mustang"
a["year"] = "1964"
fmt.Println(a)
delete(a, "year")
fmt.Println(a)
}
Синтаксис удаления из map
delete(map_name, key)
Проверка наличия элементов в map
Поиск по ключу может вернуть два значения, откуда и берётся шаблон val, ok. ok сообщает, существует ли ключ, даже когда его значение пустое, как у day в примере.
Когда вас интересует только наличие ключа, поставьте пустой идентификатор (_) на место val.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = map[string]string{"brand": "Ford", "model": "Mustang", "year": "1964", "day": ""}
val1, ok1 := a["brand"]
val2, ok2 := a["color"]
val3, ok3 := a["day"]
_, ok4 := a["model"]
fmt.Println(val1, ok1)
fmt.Println(val2, ok2)
fmt.Println(val3, ok3)
fmt.Println(ok4)
}
Синтаксис проверки map
val, ok := map_name[key]
Map являются ссылками
Переменная map ссылается на хеш-таблицу, а не содержит сами данные.
Поэтому, когда две переменные указывают на одну хеш-таблицу, изменение, сделанное через одну из них, видно и через другую.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
var a = map[string]string{"brand": "Ford", "model": "Mustang", "year": "1964"}
b := a
fmt.Println(a)
fmt.Println(b)
b["year"] = "1970"
fmt.Println("После изменения b:")
fmt.Println(a)
fmt.Println(b)
}
Перебор map
Цикл range проходит по всем ключам и значениям map. Не полагайтесь на порядок: он может меняться от запуска к запуску.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
a := map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}
for k, v := range a {
fmt.Printf("%v : %v, ", k, v)
}
}
Перебор map в определённом порядке
У map нет собственного порядка. Чтобы обойти его элементы в определённой последовательности, храните эту последовательность в другой структуре данных, например в slice ключей, и перебирайте её.
Пример
Вывод: Программа на Go и захваченный вывод
package main
import ("fmt")
func main() {
a := map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}
var b []string
b = append(b, "one", "two", "three", "four")
for k, v := range a {
fmt.Printf("%v : %v, ", k, v)
}
fmt.Println()
for _, element := range b {
fmt.Printf("%v : %v, ", element, a[element])
}
}