Typed Nil in Go

Created on Dec 5, 2025  /  Updated on Dec 5, 2025
Disclaimer: Views expressed in this software engineering blog are personal and do not represent my employer. Readers are encouraged to verify information independently.

Guess the output

Let’s take this method which is simple nil check

func IsErrNil(err error) {
    println(err == nil)
}

Let’s start directly with snippets and guess their output

func main() {
    var err error
    fmt.Println(err)
    fmt.Println(err == nil)
    IsErrNil(err)
}

What do you think the output is?

If you think that it’s

<nil>
true
true

Then right! Easy, cause in Go default value of error is nil

Let’s go to the next snippet, here I am defining my own custom error type that satisfies the error interface in Go

type CustomErr struct{}

func (c *CustomErr) Error() string {
	if c == nil {
		return "<nil>"
	}
	return "custom error"
}

func main() {
    var myCustomErr *CustomErr
    fmt.Println(myCustomErr)
    fmt.Println(myCustomErr == nil)
    IsErrNil(myCustomErr)
}

If you think that output is

<nil>
true
true

Then it’s wrong! The correct output is

<nil>
true
false

Why?

Let’s add this function that will print the type of the error

func printType(err error) {
	t := reflect.TypeOf(err)
	v := reflect.ValueOf(err)

	if t == nil {
		fmt.Println("type = <nil>, no value")
		return
	}

	if v.Kind() == reflect.Ptr && v.IsNil() {
		fmt.Printf("type = %v, value = <nil>\n", t)
	} else {
		fmt.Printf("type = %v, value = %v\n", t, v)
	}
}

If we call printType(myCustomErr), it will output the following

type = *main.CustomErr, value = <nil>

Calling printType(err), it will output

type = <nil>, no value

Here is the catch! In Go, an interface is nil only if it’s type and value are nil

The function IsErrNil takes an interface error so the err == nil will evaluate to false in case of myCustomErr cause it’s type is not nil

Conclusion

Bugs like these sometimes can be unintuitive, so keep your tests around :)

Here is final source code code