80

I am going through "A Tour of Go" tutorial.

I would like to check the answer to this question:

Note: a call to fmt.Sprint(e) inside the Error method will send the program into an infinite loop. You can avoid this by converting e first: fmt.Sprint(float64(e)). Why?


I believe this is because when the Sprint function is called, since the error is non-nil, the Error function() will again be called, and so forth, resulting in an infinite loop.

1

2 Answers 2

101

fmt.Sprint(e) will call e.Error() to convert the value e to a string. If the Error() method calls fmt.Sprint(e), then the program recurses until out of memory.

You can break the recursion by converting the e to a value without a String or Error method.

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

4 Comments

Isn't it enough to convert e to a type which may have a String/Error method that doesn't recurse infinitely?
Yes, fmt.Sprintf("cannot Sqrt negative number: %f", e) works
But why does it try to call e.Error() to do the conversion? If I try to make it implement the Stringer interface, it doesn't try to call it. What makes it seek out to the Error() method?
@hytromo In fmt/print.go, Sprint eventually leads to handleMethods with a verb of v. The switch inside handleMethods checks if the argument satisfies the error type before Stringer, resulting in the Error() method being called instead of String().
19

fmt.Sprint(e) will invoke the following piece of codes from "fmt/print.go"

switch verb {
    case 'v', 's', 'x', 'X', 'q':
        // Is it an error or Stringer?
        // The duplication in the bodies is necessary:
        // setting handled and deferring catchPanic
        // must happen before calling the method.
        switch v := p.arg.(type) {
        case error:
            handled = true
            defer p.catchPanic(p.arg, verb, "Error")
            p.fmtString(v.Error(), verb)
            return

        case Stringer:
            handled = true
            defer p.catchPanic(p.arg, verb, "String")
            p.fmtString(v.String(), verb)
            return
        }
    }

As error case appears first, v.Error() will be executed. Endless loop here!

1 Comment

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.