Nil slice — zero value, no backing array, pointer/length/capacity all zero. Empty slice — has backing array but no elements; len == 0.
Both support the same operations identically. The key differences are in identity checks and JSON serialization.
1var nilS []int // nil2emptyS := []int{} // non-nil, empty3madeS := make([]int, 0, 10) // non-nil, empty, cap=1045fmt.Println(nilS == nil) // true6fmt.Println(emptyS == nil) // false7fmt.Println(madeS == nil) // false
JSON behavior:
1n, _ := json.Marshal(nilS) // "null"2e, _ := json.Marshal(emptyS) // "[]"
When to use:
[] not null.Common mistakes:
null vs [] mismatch.len == 0 when nil vs empty matters.append(nilSlice, ...) is safe.slices.Equal(nilS, emptyS) returns false.