1

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!

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

3 Comments

Thanks for the explanation! One more question, for struct type, GoLang has default implementation for stringer, if we implement an error interface, will it confuse the fmt.Println, wondering which interface to use?
Actually it is the other way around. Error() string is used before (in preference to) String() error.
@DaveC Which is funny right? as if you define both Error() string there would be no use to define String() string, atleast not on a pointer to your type struct...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.