为什么在Error()方法中调用fmt.Sprint(e)会导致无限循环?

huangapple go评论86阅读模式
英文:

Why would a call to fmt.Sprint(e) inside the Error() method result in an infinite loop?

问题

我正在进行《Go之旅》教程。

我想要检查这个问题的答案:

注意:Error方法中调用fmt.Sprint(e)会导致程序进入无限循环。你可以通过先将e转换为fmt.Sprint(float64(e))来避免这种情况。为什么?

我认为这是因为当调用Sprint函数时,由于错误是非空的,Error方法将再次被调用,如此循环下去,导致无限循环。

英文:

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?

<br>
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

得分: 94

fmt.Sprint(e)将调用e.Error()将值e转换为string。如果Error()方法调用fmt.Sprint(e),那么程序将递归调用直到内存耗尽。

你可以通过将e转换为一个没有StringError方法的值来打破递归。

英文:

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.

答案2

得分: 15

fmt.Sprint(e)将调用来自"fmt/print.go"的以下代码片段:

switch verb {
	case 'v', 's', 'x', 'X', 'q':
		// 它是一个错误还是Stringer?
		// 在这些代码块中的重复是必要的:
		// 在调用方法之前,设置handled和延迟catchPanic
		// 必须发生。
		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
		}
	}

由于错误情况首先出现,v.Error()将被执行。这里会出现无限循环!

英文:

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

switch verb {
	case &#39;v&#39;, &#39;s&#39;, &#39;x&#39;, &#39;X&#39;, &#39;q&#39;:
		// 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, &quot;Error&quot;)
			p.fmtString(v.Error(), verb)
			return

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

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

huangapple
  • 本文由 发表于 2014年12月15日 06:32:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/27474907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定