Какие операции можно безопасно выполнять с nil-слайсом в Go и почему?

Ответ

В Go nil-слайс является корректным «нулевым» значением для типа слайс. Это не аналог null-указателя из других языков, а вполне работоспособная структура с длиной и емкостью, равными нулю. Поэтому с ним можно безопасно выполнять ряд операций:

  1. len(s): вернет 0.
  2. cap(s): вернет 0.
  3. append(s, ...): создаст новый нижележащий массив и вернет новый слайс с добавленными элементами. Это идиоматичный способ инициализации и наполнения слайса.
  4. for range s: цикл просто не выполнится ни разу, не вызвав паники. Это очень удобно при итерации по слайсам, которые могут быть не инициализированы.
  5. Сравнение с nil: s == nil вернет true.

Пример:

package main

import "fmt"

func main() {
    var s []int // s is a nil slice

    fmt.Printf("s: %v, len: %d, cap: %d, is nil: %tn", s, len(s), cap(s), s == nil)
    // Вывод: s: [], len: 0, cap: 0, is nil: true

    // append к nil-слайсу работает корректно
    s = append(s, 1, 2, 3)
    fmt.Printf("s: %v, len: %d, cap: %d, is nil: %tn", s, len(s), cap(s), s == nil)
    // Вывод: s: [1 2 3], len: 3, cap: 4, is nil: false

    // range по nil-слайсу безопасен
    var nilSlice []string
    for i, v := range nilSlice {
        fmt.Printf("Этот код никогда не выполнится: %d, %s", i, v)
    }
}

Что вызовет панику:

Попытка доступа к элементу по индексу (s[0]) или создание саб-слайса (s[1:2]) на nil-слайсе приведет к панике panic: runtime error: index out of range.