Returning nil custom error type

Below codes are about a function that returning nil custom error in two variations. Expectantly, these codes should always exit successfully, but it didn’t happen on Code 2.

Code 1

Code 2

If we change operation() return signature to error interface instead, Code 2 able to exit again.

func operation() ([]byte, error) {
	return nil, nil
}

Can someone please explain the mechanism behind it? And what’s the difference between these two exactly? Thanks.

1 Like

The section about pointers in the tour should help.

In Code 2:

package main

import "fmt"

type customError struct{}

func (c *customError) Error() string {
	return "custom error!"
}

func operation() ([]byte, *customError) {
	return nil, nil
}

func main() {
	var err error
	
	fmt.Println(err) //here, err is a nil pointer to error interface
	
	_, err = operation()
	
	fmt.Println(err) //here, err is pointer to nil customError interface, err is not nil itself
	
	if err != nil {
		println("ERROR!!!! ARRG!")
		return
	}
	
	println("peace out")
}

You can see the output here: https://play.golang.org/p/uvtktWe2MlS

You can fix Code 2 as following:

package main

type customError struct{}

func (c *customError) Error() string {
	return "custom error!"
}

func operation() ([]byte, *customError) {
	return nil, nil
}

func main() {
	var err *customError
	_, err = operation()

	if err != nil {
		println("ERROR!!!! ARRG!")
		return
	}

	println("peace out")
}

You can see the fixed output here: https://play.golang.org/p/z4tVkriX30O

For better understanding please check following code:

package main

type customError struct{}

func (c *customError) Error() string {
	return "custom error!"
}

func operation() ([]byte, *customError) {
	return nil, nil
	//return nil, &customError //how to return a custom error
}

func main() {
	var err error
	_, err = operation()
	
	if err != (*customError)(nil) { //here, we are checking if err is not equal to a pointer to nil custom error
		println("ERROR!!!! ARRG!")
		return
	}
	
	println("peace out")
}

You can see the output here: https://play.golang.org/p/RhPkEOjl--p

2 Likes

Go: Frequently Asked Questions (FAQ)

Why is my nil error value not equal to nil?


For the original design for Go interfaces:

Go Data Structures: Interfaces
Posted on Tuesday, December 1, 2009.


For err == nil it has to have a type of nil and a value of nil, but err is set to a concrete type of *customError and a concrete value of nil and err != nil.

Instead, write:

package main

import "fmt"

type customError struct{}

func (c *customError) Error() string {
	if c == nil {
		return "custom nil!"
	}
	return "custom error!"
}

func operation() ([]byte, *customError) {
	return nil, nil
}

func main() {
	var err error
	fmt.Printf("%[1]T %[1]v\n", err)
	_, err = operation()
	fmt.Printf("%[1]T %[1]v\n", err)

	if v, ok := err.(*customError); ok && v != nil {
		println("ERROR!!!! ARRG!")
		return
	}

	println("peace out")
}

https://play.golang.org/p/FM3YsnF2N3-

<nil> <nil>
*main.customError custom nil!
peace out
4 Likes

Thanks, Petrus! the FAQ hits the spot. The article about go interface is worth giving a read.

Appreciate that you spend effort to answer my newb question. :smiley:

1 Like