满足错误接口的结构的此nil实例未显示为nil

This should be a gimme for someone. Why do I not get what I expect ("Error is not nil") here?

http://play.golang.org/p/s8CWQxobVL

type Goof struct {}

func (goof *Goof) Error() string {
    return fmt.Sprintf("I'm a goof")
}

func TestError(err error) {
    if err == nil {
        fmt.Println("Error is nil")
    } else {
        fmt.Println("Error is not nil")
    }
}

func main() {
    var g *Goof // nil
    TestError(g) // expect "Error is nil"
}

This is, it turns out, a Frequently Asked Question about Go, and the short answer is that interface comparisons compare the type and the value, and (*Goof)(nil) and error(nil) have different types.

Since if err != nil is standard, you want a return value that'll work with it. You could declare var err error instead of var g *Goof: err's zero value is conveniently error(nil)

Or, if your func returns an error, return nil will return what you want.

For more background, here's the start of the FAQ's answer:

Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).

An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.

And == is strictly checking if the types are identical, not if a type (*Goof) implements an interface (error). Check out the original for more.

If it helps clarify, this doesn't only happen with nil: in this example, the data underlying the x and y variables is obviously 3, but they have different types. When you put x and y into interface{}s, they compare as unequal:

package main

import "fmt"

type Bob int

func main() {
    var x int = 3
    var y Bob = 3
    var ix, iy interface{} = x, y
    fmt.Println(ix == iy)
}