go – Why is this zero length and zero capacity slice not nil?-ThrowExceptions

Exception or error:

I’m going through a Go tutorial and I reached the lesson about nil slices where it says:

A nil slice has a length and capacity of 0 and has no underlying array.

In order to show this they present this code which works

package main

import "fmt"

func main() {
    var s []int 
    fmt.Println(s, len(s), cap(s))
    if s == nil {
        fmt.Println("nil!")
    }
}

However, I tried to experiment and I replaced var s []int with s := []int{}. The console still prints [] 0 0 as in the first case but no longer the nil! string. So why is the first one nil and the other one not?

How to solve:

For s := []int{}:
Because it is initialized to a new type (e.g. struct) with an underlying array, a length, and a capacity

A slice, once initialized, is always associated with an underlying array that holds its elements.

For var s []int see Slice types:

The value of an uninitialized slice is nil.

The zero value:

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 initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.
These two simple declarations are equivalent:

var i int
var i int = 0

After

type T struct { i int; f float64; next *T }
t := new(T)

the following holds:

t.i == 0
t.f == 0.0
t.next == nil

The same would also be true after

var t T

I hope this helps.

Leave a Reply

Your email address will not be published. Required fields are marked *