Nil in Golang
Are nil
and null
the same thing?
Coming from Java or other programming language background you might think they are but they partly are the same yet somewhat different.
nil
is a predeclared identifier in Go that represents zero values for pointers, interfaces, channels, maps, slices and function types. nil
being the zero value of pointers and interfaces, uninitialized pointers and interfaces will be nil.
So does that mean a string can’t be nil, yes you are right, a string doesn’t qualify to be either of the above-mentioned types and hence can’t be assigned nil
.
So what if I do a shorthand declaration with nil
a := nil
This will be a compile-time error use of untyped nil
since nil is untyped and the only untyped value that doesn’t have default type and the compiler has no idea which type it has to assign to a.
Okay now Let’s try to assign a value to a qualified type( a pointer)
var *a int = nil
Yes, this works as expected.
What if I try to return nil from a function
The above program will panic with this error though it will not be a compile-time error since we are returning a nil pointer which is a qualified type for nil
But when we try to reference the ‘str’ attribute of the struct, it will crash.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x1092534]
Can we compare two nil values of the same type?
Depends. Let us look at these two code snippets
var m []int = nilvar n []int = nilif m == n { fmt.Println("equal")}
This will result in compile time error
invalid operation: m == n (slice can only be compared to nil)
Let's look at this one
var i someIntf = nilvar j someIntf = nilif i == j{fmt.Println("equal")}
This works and prints “equal”
Why did it happen?
Because In Go, map, slice and function types don’t support comparison. Comparing two nil values of incomparable types is not allowed.
But uncomparable types can be compared with the bare nil
identifier
var m []int = nilvar n []int = nilif m == nil && n == nil { fmt.Println("both are nil")}
error and nil
error is an interface and hence qualify to assigned as nilif err!=nil{
fmt.Println("error encountered"}
Ranging over Nil channels
Ranging over a nil channel will block the current goroutine forever
for range chan bool(nil) { // block here
fmt.Println("nil ")
}
Ranging over nil slices and maps.
for range []int(nil) {
fmt.Println("nil slice")
}
for range map[string]string(nil) {
fmt.Println("nil map")
}
The number of loop iterations by nil maps and slices is zero. Hence this code snippet won’t print anything.
I hope that helps to understand a little bit about nil !!!