I was following the example https://tour.golang.org/moretypes/10 I modified the code expecting to get the same result. I did not. Is this a bug, or a documentation error? The tour states
A nil slice has a length and capacity of 0.
My y variable has a length and capacity of 0.
package main
import "fmt"
func myPrint(z []int) {
fmt.Println(z, len(z), cap(z))
if z == nil {
fmt.Println("nil!")
}
}
func main() {
var z []int
y := []int {}
myPrint(z)
myPrint(y)
}
Here is my output.
[] 0 0
nil!
[] 0 0
I was expecting a second "nil"~ Why didn't I get it?
Your
y
variable isn't the zero value for a slice. It's allocated via an empty slice literal.In this case:
You have declared a variable
z
but you did not initialize it.In this case:
You declared it and initialized it, you set it to an empty slice. Writing the second expression the long way makes the difference between the two expressions more clear:
The doc you referenced states that a nil slice has a length and capacity of 0, but not that every slice of length and capacity of zero is a nil slice. The specification only says that the value of an uninitialized slice is nil.
This is a convenience to support
len
andcap
on slices which are uninitialised (nil). Otherwise we would need to check for non-nil first in order to avoid panic. (This also holds for other in-built types like maps or channels.)In terms of the
fmt.Print
output, the difference in behaviour is similar to printing an uninitialised (nil) pointer vs pointer to an empty structure:nil
Vsempty
sliceIf we think of a slice like this:
then:
var s []string => no underlying array var s = []string => create a underlying array but his length is 0.