skip to content
Alvin Lucillo

Error gotcha in Go

/ 2 min read

💻 Tech

Why does the code below fail? If checkError() returns a nil value, then err != nil shouldn’t be true, right? But the program exists with Failed, so err must not be a nil.

Interface stores value and type. When checkError returns a nil value of type *customErrorType, it’s stored to variable err of type error. This is acceptable because the custom error implements Error(). But now, err is no longer just containing a nil value; it’s now an interface value holding type and value, which is not equal to a nil value. There are two ways to remediate this:

  1. Change the return type of checkError() to error. This way, we’re not returning a concrete type but just a nil error.
  2. Make the err in the scope of if condition like so: err := checkError(). This way, you’re going to check if the pointer value is nil or not.
import (
	"fmt"
	"log"
)

type customErrorType struct{}

func (c *customErrorType) Error() string {
	return "Some error"
}

func checkError() *customErrorType {
	return nil
}

func main() {
	var err error
	fmt.Printf("Type: %T\n", err) // <nil>

	if err = checkError(); err != nil {
		fmt.Printf("Type: %T\n", err) // *main.customErrorType
		log.Fatal("Failed") // This is printed, then program exists
	}

	log.Println("Successful") // Not reached
}