Nil Nil Interface Comparison Puzzle
Despite satisfying the error interface, a struct with a nil instance does not behave as expected when compared to nil.
Question:
Why does the following code not output "Error is nil"?
<code class="go">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 not nil" }</code>
Answer:
In Go, interface comparisons consider both type and value. While the Goof type implements the error interface, a nil instance of Goof (*Goof)(nil) has a distinct type from error(nil).
Solution:
To address this, you can adopt one of the following approaches:
For more details, refer to the extended response below:
Extended Response:
Interface values consist of two components: a type and a dynamic value. A nil interface value contains both a nil type and a nil value. In our case, (*Goof)(nil) has a non-nil type (Goof), but a nil value.
Additionally, Go's equality operator (==) strictly checks for type identity. Hence, comparing (*Goof)(nil) to error(nil) fails because they are of different types.
This behavior is consistent with other type-checking in Go. For instance, in the following code, the underlying data is the same (3), but the variables have different types, resulting in inequality when stored in interfaces:
<code class="go">var x int = 3 var y Bob = 3 var ix, iy interface{} = x, y fmt.Println(ix == iy) // false</code>
The above is the detailed content of Why does a nil instance of a struct that satisfies the error interface not compare equal to nil?. For more information, please follow other related articles on the PHP Chinese website!