Andrew's Digital Garden

Nil in Go (interfaces)

An interface value is nil only if the V and T are both unset - T=nil, V is not set

Although an interface is nil by default, if we store a nil pointer (e.g. of type *int) as the value for an interface, the interface's type will be *int regardless of the underling value of the pointer. Thus, the interface itself will be non-nil even though the pointer's value is nil.

An interface value that holds a nil concrete value is itself non-nil If the concrete value inside the interface itself is nil, the method will be called with a nil receiver.

var p *int var i DocsInterface i = p // i is now T=*int,V=memory address, *i = nil // i is non-nil

This also works when not talking about simple pointers, e.g. a type, pointer to a struct, etc. When the value is converted into an interface, the interface becomes non-nil as it's storing the type, even though the underlying value is nil. If the interface is used as an argument to a method, the interface datastructure is created when called, which uses the value of whatever is satisfying the interface.

Example

In this case, VError implements the interface of error. When passing something of type VError to a function that had an error interface as an argument, the value passed will always be non-nil as the interface will be storing T=VError, even if V is nil.

func (e Error) Error() { // implementation not important, but this satisfies the interface } type VError map[string]string // same is VError was a struct and verr was verr = *VError func doSomethingWithAnError(e error) { // ... } var err error var verr VError err = verr fmt.Printf("err: %T %#v \n", err, err) // main.VError main.VError(nil) fmt.Printf("err2: %T %#v \n", err2, err2) // <nil> <nil> fmt.Printf("verr == nil: %v \n", verr == nil) // true fmt.Printf("err == nil: %v \n", err == nil) // false doSomethingWithAnError(err) // this will pass a non-nil value

[[go]]

Referred in

Nil in Go (interfaces)