Interfaces · 3 MIN READ
A nil pointer in an interface is not a nil interface
Explain why err != nil can be true when the error is nil.
An interface value holds a dynamic type and a dynamic value. It is nil only when it holds neither. Assigning a nil *MyError to an error variable preserves the pointer type, so err != nil is true even though its contained pointer is nil.
When a function returns an error interface, return literal nil on the success path rather than a typed nil pointer. Calling a method on an interface holding a nil pointer is safe only if that method deliberately supports a nil receiver.
SEE THE IDEA
An interface carries a type and a value
- 01
Nil interface
govar x anyNo dynamic type and no value
- 02
Typed nil
govar p *Item = nilA pointer type with a nil value
- 03
Boxed pointer
gox = pDynamic type exists, so x != nil
Both parts must be absent for the interface itself to be nil.
In practice
An interface holding a typed nil pointer still has a dynamic type. This commonly appears when a function returns an error interface from a typed pointer variable. Return a literal nil on the success path, and make nil-receiver behavior explicit for methods intended to support it.
Watch out
An interface nil check does not prove that calling a method on the contained value is safe.
Read and predict
package main
import "fmt"
type PathError struct{ Path string }
func (e *PathError) Error() string { return "bad path: " + e.Path }
func find(name string) *PathError { return nil }
func check(name string) error { return find(name) }
func main() {
fmt.Println(check("ok") == nil)
}Does this print true or false, and why?
Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.
Progress stays in this browser. No account needed.