Reputation: 13
Firstly, I am not quite sure if this problem is more relevant to error, or to interface in GoLang
I am catching up the GoLang by following the tutorial. The question came with this tutorial page
It is a basic demonstration of the error interface. When I change the code a bit like this, I got confused:
package main
import (
"fmt"
"time"
)
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() *MyError {
return &MyError{
time.Now(), "it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
err1 := MyError{time.Now(), "it works again"}
fmt.Println(err1)
fmt.Println(err1.Error())
}
The output of this piece of code is:
at 2015-04-06 15:00:07.1541719 +0800 CST, it didn't work
{2015-04-06 15:00:07.155172 +0800 CST it works again}
at 2015-04-06 15:00:07.155172 +0800 CST, it works again
The thing confused me is under what condition the fmt will implicitly call MyError.Error() interface.
To my understanding, the first and second fmt.Println() should have the same variable type: MyError. But obviously the first call involved an implicit call of Error() of the MyError type, while the second did not.
What mechanism made this difference?
Thanks for looking into this beginner's question!
Upvotes: 1
Views: 3382
Reputation: 6864
Your code binds the Error() implementation to a pointer *MyError.
In your code you are passing the type (a copy thereof to be precise) rather than a pointer.
If you change
err1 := MyError{time.Now(), "it works again"}
to
err1 := &MyError{time.Now(), "it works again"}
it will work as you expect.
Upvotes: 1
Reputation: 1
fmt.Println
uses reflection to firstly check the type of the variable and if the type implements the Stringer
interface then it calls the String
method. Secondly if the type implements the Error
interface it calls the Error
method.
Upvotes: 0