← Назад к вопросам

Что будет при append в слайсе, объявленном без параметров?

1.6 Junior🔥 82 комментариев
#Основы Go

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Поведение append для nil-слайса в Go

При вызове функции append для слайса, объявленного без параметров (что создаёт nil-слайс), в Go происходит корректное создание нового слайса с добавленными элементами. Это одно из ключевых преимуществ работы со слайсами в Go — nil-слайсы являются полностью функциональными и безопасными для большинства операций.

Что такое nil-слайс?

Слайс, объявленный без параметров, имеет нулевое значение — nil:

var s []int          // s == nil, len(s) == 0, cap(s) == 0
var s2 = []int{}     // s2 != nil, len(s2) == 0, cap(s2) == 0 (пустой, но не nil)

Поведение append с nil-слайсом

Когда вызывается append для nil-слайса, Go автоматически выделяет память и создаёт новый слайс:

var s []int          // nil-слайс
s = append(s, 1)     // Создаётся новый слайс с элементом 1
fmt.Println(s)       // [1]
fmt.Println(s == nil) // false

Внутренняя механика

Под капотом функция append:

  1. Проверяет, достаточно ли ёмкости (capacity) в текущем слайсе
  2. Если слайс nil или ёмкости недостаточно — выделяет новый массив
  3. Копирует существующие элементы (если были) в новый массив
  4. Добавляет новые элементы
  5. Возвращает новый слайс
package main

import "fmt"

func main() {
    var nilSlice []string
    fmt.Printf("До append: %v, len=%d, cap=%d, is nil=%v\n", 
        nilSlice, len(nilSlice), cap(nilSlice), nilSlice == nil)
    
    // Append в nil-слайс
    nilSlice = append(nilSlice, "hello", "world")
    fmt.Printf("После append: %v, len=%d, cap=%d, is nil=%v\n", 
        nilSlice, len(nilSlice), cap(nilSlice), nilSlice == nil)
    
    // Демонстрация ёмкости
    var s []int
    for i := 0; i < 10; i++ {
        fmt.Printf("len=%d cap=%d\n", len(s), cap(s))
        s = append(s, i)
    }
}

Практические последствия

Преимущества:

  • Безопасность — не нужно предварительно инициализировать слайс перед использованием append
  • Удобство — можно объявить переменную и отложить её заполнение
  • Эффективность — nil-слайс не потребляет память до первого append

Важные нюансы:

  1. Первое выделение памяти происходит только при первом append
  2. Начальная ёмкость определяется алгоритмом Go (обычно 2 для первого элемента, затем по формуле роста)
  3. Возвращаемое значение — всегда новый слайс, даже если исходный был nil

Сравнение с пустым слайсом

// nil-слайс
var nilSlice []int            // Не выделяет память под массив

// Пустой слайс
emptySlice := []int{}         // Выделяет память под пустой массив
emptySlice2 := make([]int, 0) // Явное создание пустого слайса

// Все три варианта работают с append одинаково:
nilSlice = append(nilSlice, 1)     // Выделит память
emptySlice = append(emptySlice, 1) // Может выделить новую память

Рекомендации по использованию

  1. Используйте nil-слайс по умолчанию, когда не знаете начальный размер
  2. Проверка на nil всё ещё важна для логики, отличающей "отсутствие данных" от "пустой коллекции"
  3. Для JSON-сериализации nil-слайсы сериализуются в null, а пустые — в []
// Пример: обработка отсутствующих данных
func processItems(items []string) {
    if items == nil {
        // Данные не были предоставлены
        return
    }
    if len(items) == 0 {
        // Предоставлен пустой список
        fmt.Println("Список пуст")
    }
    // Обработка элементов
}

Вывод

Функция append в Go специально разработана для безопасной работы с nil-слайсами, что делает код чище и уменьшает количество шаблонной проверки инициализации. Это дизайнерское решение позволяет разработчикам объявлять переменные слайсов без немедленной инициализации, откладывая выделение памяти до момента фактической необходимости.

Что будет при append в слайсе, объявленном без параметров? | PrepBro