I'm trying to understand golang interface, my problem is that why err2.What undefined.
Here is a simple code. The output indicates that both err and err2 have same type as *main.MyError, but err2 have no field "What", so there must be some difference between err and err2, but I cannot figure out the difference here. I just began learning golang not long before, any help will be greatly appreciated.
package main
import (
"fmt"
"time"
"reflect"
)
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
err := &MyError{time.Now(), "Hello"}
fmt.Println(reflect.TypeOf(err))
fmt.Println(err.What)
err2 := run()
fmt.Println(reflect.TypeOf(err2))
fmt.Println(err2.What)
}
main.MyError
Hello
main.MyError
it didn't work
\# command-line-arguments ./test.go:34:18: err2.What undefined (type error has no field or method What)
The function run()
returns a value of type error
, which is an interface type. Yes, it wraps a value of concrete type *MyError
, but to get access to MyError
's fields, you need to use a type assertion:
fmt.Println(err2.(*MyError).What)
Try it on the Go Playground.
Note that a value of error
type may contain values of other concrete types, actually any that implements the error
interface. If it would contain a value of another type, the above type assertion would result in a runtime panic.
If you're unsure err2
actually holds a value of type *MyError
and you want to avoid the runtime panic, you may use the special form of type assertion to get this information and only act if it is so:
if myerror, ok := err2.(*MyError); ok {
fmt.Println(myerror.What) // Here myerror has static type *MyError
} else {
fmt.Println("Some other error:", err2)
}
Try this one on the Go Playground.
I think the interface of error type is let you use Error()
method without any detail in the concrete structure. You can check on the Go Playground