Nil in Go
nil
in Go
What is nil
in Go has several meanings:
- It represents "null" in Go. This means two things: 1. It does not have type. 2. Its value is "null".
- It is a predeclared identifier in Go, which means you can use it without declaring it.
- It represents zero values (and default values) of some types in Go, including:
- interface types
- pointer types
- slice types
- map types
- channel types
- function types
nil
as Zero Values
Using nil
represents zero values (and default values) of some types in Go.
Example: https://gist.github.com/d1c9fa6273aa11c087fb304ed395fe7d
nil
in Comparison
Using nil
Values of Two Different Types Are Not Comparable
Two Example: https://gist.github.com/d86f6b1d85e6194d2617ea5fe6b290b1
These code will fail to compile as they are trying to compare nil
values of two different types.
nil
Values of The Same Type May Not Be Comparable
Two Example: https://gist.github.com/327a0625cf92c10cde3985f83ba7368c
Take var sb = (map[string]bool)(nil) == (map[string]bool)(nil)
as an example, the reason why two nil
values of a same type (map[string]bool
) are not comparable is because Go does not support comparison in slice, map and function types. You can see that we are comparing two values of a non-comparable type in this case. That is why it fails.
But the following code works and results are true:
https://gist.github.com/f158575db9b1813f9369533815028c0f
Take var sb = (map[string]bool)(nil) == nil
as an example, (map[string]bool)(nil)
declares a map[string]bool
temporary variable which value is nil
and (map[string]bool)(nil) == nil
detects whether the variable's value is nil
and then assigns the results to sb
. You can see that we are comparing the value of a non-comparable type with its zero value (nil
) in this case. That's why it works.
nil
Values of The Same Type Can Be Comparable Only When This Type Supports Comparision
Two Example: https://gist.github.com/63ca0182dca2c8e9c89a89d63dc00edf
nil
Comparision When Interface Values Are Involved
Be Careful in The following code will not cause any compiler failure but the result is false
other than true
.
https://gist.github.com/42523b5f818e2a0dbf0da1df1a205120
Explanation:
- An interface value consists of a dynamic type and a dynamic value.
interface{}(nil)
declares an interface value with{type: nil, value: nil}
. - The non-interface value is converted to the type of the interface value before making the comparison with an interface value. In this example,
(*int)(nil)
is converted to an interface value with{type: *int, value: nil}
. - Two
nil
interface values are equivalent only when they carry the same type. In this case, the converted interface value{type: *int, value: nil}
has a concrete dynamic type but the other interface value has not. That is why the comparison result isfalse
.
A more interesting example: https://gist.github.com/a67a6e1cea706a787e017f0786479e13
Explanation:
- An interface value equals to
nil
only when its type and value are bothnil
. In example,w
is anio.Writer
interface value with{type: *bytes.Buffer, value: nil}
after thew = b
assignment. Therefore,w == nil
isfalse
as it carries*bytes.Buffer
other thannil
as its concrete dynamic type.
Summary
nil
is and a pre-declared identifier which can be used to represent the zero values of some types in Go.- Be careful when using
nil
in comparison, especially when interface values are involved. You need to understand what you are comparing: types, or values, or both. (a thing)(nil)
may not equal tonil
, depends on what that thing is (a pointer or an interface). This means Go is a strong-type language and it also applies tonil
even thoughnil
itself does not have default type (sarcasm).