В чем разница слайсов и массивов
Слайсы и массивы в Go — это две структуры данных для хранения последовательностей элементов, но они принципиально различаются: массив имеет фиксированный размер, задаваемый при объявлении, а слайс — динамическое «окно» в базовый массив, размер которого может меняться. Массив — это значение, хранящее элементы непосредственно, а слайс — это структура из указателя на массив, длины и вместимости.
Как это работает
Массив объявляется с указанием размера, который является частью его типа. Например, [5]int и [10]int — это разные типы. Размер массива нельзя изменить после объявления, и он хранит свои элементы в памяти как единое целое.
Слайс создается без указания размера или через функцию make. Он ссылается на массив, который может быть создан автоматически или передан извне. Слайс содержит три компонента: указатель на первый элемент массива, длину (количество доступных элементов) и вместимость (максимальное количество элементов до перераспределения). При добавлении элементов через append, если вместимость исчерпана, Go выделяет новый массив большего размера и копирует данные.
// Массив фиксированного размера
var arr [5]int
// Слайс, ссылающийся на массив из трех элементов
s := []int{1, 2, 3}
// Слайс с указанием длины и вместимости
s2 := make([]int, 3, 5)Основные различия
| Критерий | Массив | Слайс |
|---|---|---|
| Размер | Фиксированный, задается при объявлении | Динамический, может изменяться |
| Тип | Размер входит в тип ([5]int ≠ [10]int) | Размер не входит в тип ([]int для любой длины) |
| Хранение | Хранит элементы напрямую | Ссылается на массив, хранит указатель, длину и вместимость |
| Производительность | Прямой доступ к памяти, быстрее | Дополнительная индирекция, чуть медленнее |
| Использование | Когда количество элементов известно и не меняется | Когда количество элементов может меняться или нужна работа с подмассивом |
Подводные камни
- При передаче массива в функцию он копируется целиком, что может быть дорого для больших массивов. Слайс передается по ссылке, но изменения внутри функции могут повлиять на исходный массив, если не использовать копирование.
- Слайс — это ссылка на массив. Если два слайса ссылаются на один и тот же массив, изменение одного может отразиться на другом.
- Операция
appendможет изменить вместимость и создать новый массив, что приведет к потере связи с исходным массивом. - Сравнение слайсов напрямую с помощью
==невозможно (кроме сравнения сnil), в отличие от массивов, которые сравнимы.
Когда использовать
Массивы стоит использовать в редких случаях, когда точный размер известен заранее и не изменится, например, для фиксированных матриц или хэш-таблиц. В подавляющем большинстве случаев предпочтительны слайсы: они гибкие, удобные для передачи в функции и работы с динамическими данными. Даже если размер известен, часто используют слайс с фиксированной длиной, чтобы сохранить возможность расширения.
Коротко
- Массив — фиксированный размер, часть типа; слайс — динамический, ссылается на массив.
- Слайс состоит из указателя, длины и вместимости;
appendуправляет расширением. - Слайсы удобнее для большинства задач, массивы — для фиксированных последовательностей.
- При передаче в функции слайсы эффективнее, но требуют осторожности с изменениями.
