Эта глава — одна из самых важных. В Go коллекции данных (массивы, срезы и карты) используются повсеместно. Если массивы в Go встречаются редко, то срезы (slices) — это «хлеб и соль» любого Go-разработчика.
В этой главе мы изучим, как группировать данные в Go. Мы рассмотрим три основных типа коллекций: массивы (фиксированный размер), срезы (динамический размер) и карты (пары ключ-значение).
Массивы (Arrays)
Массив — это нумерованная последовательность элементов одного типа с фиксированной длиной. В Go длина является частью типа массива. Это значит, что [5]int и [10]int — это абсолютно разные типы данных.
var x [5]int
x[4] = 100
fmt.Println(x) // Выведет [0 0 0 0 100]
- Индексация начинается с 0.
- Массивы редко используются в Go напрямую, так как их размер нельзя изменить. Чаще они служат фундаментом для срезов.
Срезы (Slices)
Срез — это сегмент массива. В отличие от массивов, срезы могут изменять свою длину. Срез состоит из трех компонентов: указатель на массив, длина (length) и емкость (capacity).
Создание среза
// С помощью функции make: тип, длина, емкость (опционально)
x := make([]float64, 5, 10)
Здесь 5 — текущая длина (доступные элементы), а 10 — емкость (сколько элементов срез может вместить без выделения новой памяти).
Выражение [low : high]
Вы можете «отрезать» часть от массива или другого среза:
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // Элементы с индексами 1, 2, 3 -> [2, 3, 4]
Функции append и copy
append — добавляет элементы в конец среза. Если места в текущей емкости не хватает, Go создаст новый массив большего размера автоматически.
slice := []int{1, 2, 3}
slice = append(slice, 4, 5) // [1, 2, 3, 4, 5]
[!TIP] Пакет slices В современном Go (начиная с 1.21) есть стандартный пакет
slicesдля удобной работы (сортировка, поиск, реверс). Например:slices.Sort(slice).
Карты (Maps)
Карта — это неупорядоченная коллекция пар ключ-значение. В других языках их называют словарями (Python) или хэш-таблицами (Java).
Инициализация
Важно: Карта должна быть инициализирована через make, иначе при попытке записи программа “упадет” (panic).
elements := make(map[string]string)
elements["H"] = "Hydrogen"
fmt.Println(elements["H"])
Проверка существования (Comma ok idiom)
Если ключа в карте нет, Go вернет “нулевое значение” (например, пустую строку). Чтобы понять, был ли ключ на самом деле, используйте второй результат:
name, ok := elements["Un"]
if ok {
fmt.Println(name)
} else {
fmt.Println("Элемент не найден")
}
Удаление
Для удаления используется встроенная функция delete(map, key).
Итоговый пример: Сложные структуры
Карты могут содержать другие карты или срезы:
func main() {
// Карта, где ключ - строка, а значение - другая карта
elements := map[string]map[string]string{
"H": {"name": "Hydrogen", "state": "gas"},
"Li": {"name": "Lithium", "state": "solid"},
}
if el, ok := elements["Li"]; ok {
fmt.Printf("Имя: %s, Состояние: %s\n", el["name"], el["state"])
}
}
Задачи
- Доступ: Как получить доступ к 4-му элементу среза
s? - Длина и емкость: Чему равны
lenиcapу срезаmake([]int, 5, 15)? - Срезы: Дан массив
x := [6]string{"a","b","c","d","e","f"}. Что выведетfmt.Println(x[2:5])? - Алгоритм: Напишите программу, которая находит минимальное число в срезе: ```go x := []int{48, 96, 86, 68, 57, 82, 63, 70, 37, 34, 83, 27, 19, 97, 9, 17}
```
- Карты: Напишите программу, которая считает количество повторений каждого слова в строке (подсказка: используйте
strings.Fields).
Полезные ссылки
- Go Blog: Arrays, slices (and strings) — обязательное чтение для понимания механики срезов.
- Go by Example: Slices и Maps.
- Пакет slices (Go 1.21+) — современные функции для работы со срезами.