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

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

1.7 Middle🔥 231 комментариев
#Основы Go

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

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

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

Краткий ответ

Если объявить slice (срез) в Go, но не инициализировать его явным значением, переменная будет иметь нулевое значение для типа slice, то есть nil. Визуально это можно представить как:

var s []int // s == nil, len(s) == 0, cap(s) == 0

Подробное объяснение

В Go объявление переменной без явной инициализации всегда присваивает ей нулевое значение (zero value) для её типа. Для slice нулевое значение — это nil.

Как выглядит неинициализированный slice

package main

import "fmt"

func main() {
    var uninitializedSlice []string // Объявление без инициализации
    fmt.Printf("Значение: %v\n", uninitializedSlice)
    fmt.Printf("Равен nil: %t\n", uninitializedSlice == nil)
    fmt.Printf("Длина: %d\n", len(uninitializedSlice))
    fmt.Printf("Ёмкость: %d\n", cap(uninitializedSlice))
    fmt.Printf("Тип: %T\n", uninitializedSlice)
}

Вывод этого кода:

Значение: []
Равен nil: true
Длина: 0
Ёмкость: 0
Тип: []string

Важно отметить, что nil slice отображается как пустой массив [], но технически отличается от проинициализированного пустого slice.

Сравнение с инициализированными slice

Рассмотрим различия:

var nilSlice []int               // nil slice (нулевое значение)
emptySlice := []int{}            // Пустой, но не nil slice
makeSlice := make([]int, 0)      // Пустой slice через make
literalSlice := []int{1, 2, 3}   // Инициализированный с элементами

fmt.Println(nilSlice == nil)      // true
fmt.Println(emptySlice == nil)    // false
fmt.Println(makeSlice == nil)     // false

Все три варианта — nilSlice, emptySlice и makeSlice — имеют длину 0 и ёмкость 0, и их можно безопасно использовать в большинстве операций (итерация, append), но только nilSlice равен nil.

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

  1. Безопасность операций: Все nil slice безопасны для:
    • Вызова len() и cap() (вернёт 0)
    • Итерации в range (не выполнит ни одной итерации)
    • Использования в append() (создаст новый slice)
var s []int
for i, v := range s {
    // Этот блок кода никогда не выполнится
}
s = append(s, 42) // Создаст новый slice [42]
  1. Проверка на nil: Распространённый паттерн в Go — проверка slice на nil, что удобно для различения "отсутствия значения" от "пустой коллекции".

  2. Особенности JSON-сериализации: При сериализации в JSON, nil slice становится null, а пустой slice — [].

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

  • Явно указывайте nil для семантики "отсутствия значения":

    // Хорошо - явно показывает намерение
    var items []Item = nil
    if items == nil {
        // Логика обработки отсутствия данных
    }
    
  • Используйте make или литералы для работы с пустыми коллекциями:

    // Для предварительного выделения памяти
    buffer := make([]byte, 0, 1024)
    
    // Для готового к использованию пустого slice
    results := []Result{}
    
  • Помните о передачи nil slice в функции: Многие функции стандартной библиотеки корректно работают с nil slice, но пользовательским функциям может потребоваться проверка.

Итог

Неинициализированный slice в Go равен nil, имеет длину 0 и ёмкость 0. Его можно безопасно использовать в большинстве операций, но важно понимать семантическое различие между nil slice и пустым slice, особенно при проектировании API и обработке граничных случаев.