Using reflection to get the name or package path of the error
type in Golang causes the program to panic (with panic: runtime error: invalid memory address or nil pointer dereference
).
What is the reasoning for this behaviour? (Doing the same operation for other built in types returns the type name and an empty string for the package path.)
I'm interested in terms of the design of the language - I can't figure out why it's desirable for this to behave differently for error
types over other built in types.
E.g:
package main
import (
"fmt"
"reflect"
)
func main() {
var str string
strType := reflect.TypeOf(str)
fmt.Println(strType.Name()) // OK
fmt.Println(strType.PkgPath()) // OK
var err error
errType := reflect.TypeOf(err)
fmt.Println(errType.Name()) // panics
fmt.Println(errType.PkgPath()) // also panics
}
Go playground here: https://play.golang.org/p/JBMhMkjGPEV
error
is not special, except that it's an interface.
reflect.TypeOf
takes a single argument of type interface{}
. If you call it with a non-interface value, the value and its type is wrapped in an interface{}
. If you call it with an interface value, the underlying value and type is extracted from the interface, and wrapped in a new interface{}
value. If you call it with an empty interface (like you're doing here, since error
is an interface and it's zero-initialized), then there's no underlying value and type, and the argument to reflect.TypeOf
is a new nil interface{}
value. reflect.TypeOf
is defined to return nil
in this case, leading to your nil problems.
I think your confusion is that the TypeOf
of an interface value is the type of its underlying value, which is never an interface. You would like TypeOf
of an interface value to be the interface type itself, but that's not how it works.