Skip to main content

interface comparison in Go

A colleague found error comparison failed him a day, and he asked me for help. He showed me his code and there’s something like this.

type MyErr struct {

// *MyErr implemented error interface
func (e *MyErr) Error() string {
	return "My Error"

// we do something here and return a *MyErr as an error
func getError() error {
	var err *MyErr
	return err

There’s a *MyErr implemented error interface, and getError() was defined to return an error interface. Let’s try some comparison.

println(getError() == nil) // guess what? there's a false

WTF! Go is failing me! But ….. Wait, let’s try something

println(getError().(*MyErr) == nil) //Ahhhh, it's a true

So maybe we were wrong. There must be something we don’t know about the interface comparison. And I found something I didn’t notice before in FAQ of go, Why is my nil error value not equal to nil? And the link is below if you’re interested.

Two interfaces equal if both type and value are equal. Error we returned in getError() is a *MyErr type with value nil. It’s not equal to nil because the type is *MyErr. Let’s try other types

var x, y interface{}
println(x == y) // true, both nil
x = int32(1)
y = int64(1)
println(x == y) // false, type int32 != int64
x = int64(1)
println(x == y) // true, both are int64 (type) and 1 (value)

Guess that’s it. But how to avoid bugs like this? We can always return nil instead of a variable to avoid interface comparison bugs.

func getError() error {
  if errOccur {
    return SomeErr // return a variable only if there was an error
  return nil // always return nil if there's no error