Reputation: 1897
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 theError
method will send the program into an infinite loop. You can avoid this by convertinge
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.
Upvotes: 79
Views: 10116
Reputation: 327
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!
Upvotes: 18
Reputation:
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.
Upvotes: 100