Встречается на 66% собеседований по Go

В чем разница слайсов и массивов

Слайсы и массивы в Go — это две структуры данных для хранения последовательностей элементов, но они принципиально различаются: массив имеет фиксированный размер, задаваемый при объявлении, а слайс — динамическое «окно» в базовый массив, размер которого может меняться. Массив — это значение, хранящее элементы непосредственно, а слайс — это структура из указателя на массив, длины и вместимости.

Как это работает

Массив объявляется с указанием размера, который является частью его типа. Например, [5]int и [10]int — это разные типы. Размер массива нельзя изменить после объявления, и он хранит свои элементы в памяти как единое целое.

Слайс создается без указания размера или через функцию make. Он ссылается на массив, который может быть создан автоматически или передан извне. Слайс содержит три компонента: указатель на первый элемент массива, длину (количество доступных элементов) и вместимость (максимальное количество элементов до перераспределения). При добавлении элементов через append, если вместимость исчерпана, Go выделяет новый массив большего размера и копирует данные.

go
// Массив фиксированного размера
var arr [5]int

// Слайс, ссылающийся на массив из трех элементов
s := []int{1, 2, 3}

// Слайс с указанием длины и вместимости
s2 := make([]int, 3, 5)

Основные различия

КритерийМассивСлайс
РазмерФиксированный, задается при объявленииДинамический, может изменяться
ТипРазмер входит в тип ([5]int[10]int)Размер не входит в тип ([]int для любой длины)
ХранениеХранит элементы напрямуюСсылается на массив, хранит указатель, длину и вместимость
ПроизводительностьПрямой доступ к памяти, быстрееДополнительная индирекция, чуть медленнее
ИспользованиеКогда количество элементов известно и не меняетсяКогда количество элементов может меняться или нужна работа с подмассивом

Подводные камни

  • При передаче массива в функцию он копируется целиком, что может быть дорого для больших массивов. Слайс передается по ссылке, но изменения внутри функции могут повлиять на исходный массив, если не использовать копирование.
  • Слайс — это ссылка на массив. Если два слайса ссылаются на один и тот же массив, изменение одного может отразиться на другом.
  • Операция append может изменить вместимость и создать новый массив, что приведет к потере связи с исходным массивом.
  • Сравнение слайсов напрямую с помощью == невозможно (кроме сравнения с nil), в отличие от массивов, которые сравнимы.

Когда использовать

Массивы стоит использовать в редких случаях, когда точный размер известен заранее и не изменится, например, для фиксированных матриц или хэш-таблиц. В подавляющем большинстве случаев предпочтительны слайсы: они гибкие, удобные для передачи в функции и работы с динамическими данными. Даже если размер известен, часто используют слайс с фиксированной длиной, чтобы сохранить возможность расширения.

Коротко

  • Массив — фиксированный размер, часть типа; слайс — динамический, ссылается на массив.
  • Слайс состоит из указателя, длины и вместимости; append управляет расширением.
  • Слайсы удобнее для большинства задач, массивы — для фиксированных последовательностей.
  • При передаче в функции слайсы эффективнее, но требуют осторожности с изменениями.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы