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
represents zero values (and default values) of some types in Go.
Example: https://gist.github.com/d1c9fa6273aa11c087fb304ed395fe7d
Example: https://gist.github.com/d86f6b1d85e6194d2617ea5fe6b290b1
These code will fail to compile as they are trying to compare nil
values of two different types.
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.
Example: https://gist.github.com/63ca0182dca2c8e9c89a89d63dc00edf
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.
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).