Logic behind failing Nil check?

hi all,
Im relatively new to go (but been a developer for over 15yrs) and wrote some code like this and it perplexed me for a couple hours.

var _ error = &Error{}
type Error struct{ message string }
func (e *Error) Error() string { return e.message }
func call1() error  { return call2() }
func call2() *Error { return nil }
func Test_Gotcha(t *testing.T) {
	defer func() {
		if r := recover(); r != nil {
			t.Errorf("Failed with a panic for null usage")
		}
	}()
	err := call1()
	if err != nil {
		anError, ok := err.(*Error)
		if ok {
			fmt.Printf("this panics on nil reference %s\n", anError.message)
		}
	}
}

Im wondering what the logic is behind the err!=nil not catching the <*Error> nil returned from call2?
Go seems straight pretty easy and straight forward most of the time but this seems to be a gotcha in a really bad place?
PS Im using go 13.1

This is addressed in the Go “FAQ” on the main go site. See https://golang.org/doc/faq#nil_error

4 Likes

Hello,

Can you expand to testing struct or can you share us a runing example on play golang?

Yeah thanks :).
It still does not explain the logic behind it … why does it do this? and why is it designed like this ?

hi yep … the code in the description replicated it when the anError.message panics on the value of the type being nil

One bit of the logic behind it is that nil pointers in Go aren’t always as “bad” as in other languages. For example it’s ok to call methods on nil pointers, and those methods can do useful things. This means that having an interface with T=*foo V=nil might be a useful and intended thing. Hence the nil interface is strictly the one that has no type (nor value).

In another sense it would be odd for an interface to be nil yet contain information (the type). As it is, nil strictly means the zero value which is simple and easy to understand - although it causes this annoying caveat with errors.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.