When storage is allocated for a variable, either through a declaration or a call of new , or when a new value is created, either through a composite literal or a call of make , and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps.
This page collects common comments made during reviews of Go code, so that a single detailed explanation can be referred to by shorthands. This is a laundry list of common mistakes, not a comprehensive style guide.
You can view this as a supplement to Effective Go.
The former declares a nil slice value, while the latter is non-nil but zero-length. They are functionally equivalent—their len and cap are both zero—but the nil slice is the preferred style.
Note that there are limited circumstances where a non-nil but zero-length slice is preferred, such as when encoding JSON objects (a nil slice encodes to null , while []string{} encodes to the JSON array [] ).
When designing interfaces, avoid making a distinction between a nil slice and a non-nil, zero-length slice, as this can lead to subtle programming errors.
For more discussion about nil in Go see Francesc Campoy’s talk Understanding Nil.
package main
import (
"fmt"
"unsafe"
)
type slice struct {
array unsafe.Pointer
len int
cap int
}
func main() {
var a []int
printSlice(&a)
fmt.Println()
b := []int{}
printSlice(&b)
fmt.Println()
}
func printSlice(p *[]int) {
s := *p
fmt.Printf("%[1]v %[2]p %[1]T %[3]t\n", s, p, s == nil)
ss := (*slice)(unsafe.Pointer(p))
fmt.Println(ss.array, ss.len, ss.cap)
}
The declarations of a and b allocate zero-value slice structs at 0xc00000c0a0 and 0xc00000c0c0. The assignment of the composite literal []int{} to b allocates an underlying array at 0x586a00.