Nil slice — zero value of []T; pointer is nil, length and capacity are 0. Empty slice — has a backing array but no elements; length is 0 but capacity may be > 0.
Both support the same operations: len, cap, range, and append. The practical difference appears in JSON marshaling and equality checks.
1var nilS []int // nil slice2emptyS := []int{} // non-nil, empty3madeS := make([]int, 0, 5) // non-nil, empty, cap=545// append works on all three6nilS = append(nilS, 1) // [1]7emptyS = append(emptyS, 2) // [2]8madeS = append(madeS, 3) // [3]
JSON serialization:
1n, _ := json.Marshal(nilS) // "null"2e, _ := json.Marshal(emptyS) // "[]"
When to use:
[] instead of null in JSON.Common mistakes:
[].len == 0 when nil vs empty matters.append(nilSlice, ...) panics — it doesn't.slices.Equal(nilS, emptyS) — they are not equal despite same length.