Какие способы объявления слайсов существуют в Go и в чем их различия?

Ответ

В Go есть три основных способа объявления и инициализации слайсов. Выбор способа зависит от того, известен ли заранее размер и нужно ли сразу выделить память.

1. Через var (нулевое значение)

Создает nil-слайс. Это самый "дешевый" способ, так как память под базовый массив не выделяется.

var s []int
// s == nil
// len(s) == 0, cap(s) == 0
  • Когда использовать: Когда вы хотите объявить пустой слайс, в который элементы будут добавляться позже, и вам не важно, будет он nil или нет. Это идиоматичный способ объявить пустой слайс.

2. Через make (с выделением памяти)

Функция make позволяет создать слайс с заданной длиной (len) и емкостью (cap).

// Способ А: len=5, cap=5
s1 := make([]int, 5)

// Способ Б: len=0, cap=10
s2 := make([]int, 0, 10)
  • Когда использовать: Когда вы заранее знаете примерное количество элементов, которые будут в слайсе. Указание capacity позволяет избежать многократных переаллокаций памяти при добавлении элементов через append, что повышает производительность.

3. Через литерал

Создает слайс и сразу инициализирует его значениями. Длина и емкость будут равны количеству элементов.

// Создает слайс с len=3 и cap=3
s := []int{10, 20, 30}
  • Когда использовать: Когда у вас есть начальный набор данных для слайса, например, в тестах или для конфигурационных значений.

Ключевые различия и рекомендации

СпособРезультатВнутреннее представление (указатель)Примечание
var s []Tnil-слайс (len=0, cap=0)nilИдиоматичный способ для пустого слайса. Безопасен для append и range.
s := []T{}Пустой, но не nil слайс (len=0, cap=0)Указывает на пустой массивФункционально почти идентичен nil-слайсу, но не равен nil.
s := make([]T, 0, N)Пустой, не nil слайс (len=0, cap=N)Указывает на массив размером NЛучший выбор, если размер известен заранее.

Важный аспект: append и переаллокация

Когда вы добавляете элементы в слайс с помощью append и его capacity исчерпана, Go выделяет новый, больший массив и копирует в него все старые элементы. Поэтому критически важно всегда присваивать результат append обратно в переменную слайса:

// Правильно
s = append(s, 1)

// Неправильно - может привести к потере данных, если произошла переаллокация
append(s, 1)