Go Typed Nil
TOC
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
nilonly 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 *implinitializes it tonil.iis a pointer toimpland is initialized tonil.
- Printing
i == nilinmainistrue- because
iis anilpointer toimpl
- because
- Calling
what(i)function:- the function
whattakes an argument of typeinterface{ do() }
- the function
- Inside
whatfunction:i(which isnil) is passed towhat- it is assigned to the parameter
iof typeinterface{ do() }
- Interface value construction:
The value ofiinsidewhatis 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 == nilprintsfalsebecause the interfaceiis 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.