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.
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