Go Typed Nil
The following code doesn’t do what you might expect:
package main
import "fmt"
func main() {
var i *impl
fmt.Println("i == nil:", i == nil)
what(i)
}
type impl struct{}
func (i *impl) do() {}
func what(i interface{ do() }) {
fmt.Println("i == nil:", i == nil)
}
If you expected the what
function to print i == nil: true
, then keep
reading…
Typed Nils
The behavior observed is due to the way interfaces and nil values interact in
Go. To understand why the what
function is able to see the i
argument as
non-nil, we need to dig into the details of how Go handles interface values.
- Interface Values: In Go, an interface value is a tuple of a type and a value.
An interface value is
nil
only if both the type and the value arenil
. - Concrete vs Interface nil: When you assign a concrete type value (which
happens to be
nil
) to an interface, the interface itself is notnil
. This is because the interface value now contains a type (the concrete type) and a value (nil
).
Explanation
- Declaring
var i *impl
initializes it tonil
.i
is a pointer toimpl
and is initialized tonil
.
- Printing
i == nil
inmain
istrue
- because
i
is anil
pointer toimpl
- because
- Calling
what(i)
function:- the function
what
takes an argument of typeinterface{ do() }
- the function
- Inside
what
function:i
(which isnil
) is passed towhat
- it is assigned to the parameter
i
of typeinterface{ do() }
- Interface value construction:
The value ofi
insidewhat
is now an interface that holds:- Type:
*impl
(the concrete type of the value passed in) - Value:
nil
(the value of the concrete type)
- Type:
- Checking
i == nil
printsfalse
because the interfacei
is notnil
:- The type part of the interface is
*impl
. - The value part of the interface is
nil
.
- The type part of the interface is
Summary
The what
function sees the i
argument as non-nil because, in Go, an
interface holding a nil
pointer is not itself nil
. The interface contains
type information (*impl
) and a nil
value. Therefore, when the code checks if
i
is nil
, it returns false
since the type information (*impl
) is
present.