ataraskov.dev

About everything and nothing


Custom errors and interfaces

Go error handling is almost a meme. Who hasn’t seen a joke or two about the ocean of if statements for err != nil?

Let’s consider a simple example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type CustomError struct{}

func (e CustomError) Error() string {
	return "custom error"
}

func returnError() error {
	var err error
	return err
}

func returnCustomError() error {
	var err CustomError
	return err
}

func main() {
	fmt.Println(
		"returnError()",
		returnError() == nil,
	)
	fmt.Println(
		"returnCustomError()",
		returnCustomError() == nil,
	)
}

 

What would be the output? True in both cases, obviously. Otherwise, it will break our beloved err != nil flow.

Surprise, it’s actually not:

1
2
returnError() true
returnCustomError() false

 

Go FAQ says:

Just keep in mind that if any concrete value has been stored in the interface, the interface will not be nil

So once we know the type, the interface is not nil anymore, as it holds type value internally.

References:

Sun Nov 26, 2023 / 190 words / Golang Programming Gotchas