3 回答
TA贡献1803条经验 获得超6个赞
好像直接说明就是 fmt 包的来源:
// Is it an error or Stringer?
// The duplication in the bodies is necessary:
// setting handled and deferring catchPanic
// must happen before calling the method.
然后调用Error()或String()。
这意味着第一个error.Error()被调用以生成字符串,然后再次处理并打印为字符串。
这里是否error有方法String无关紧要。问题是为什么NegativeSqrt用一种方法而不是另一种方法打印。键入NegativeSqrt同时实现了fmt.Stringer与error接口,所以它是由执行fmt封装的接口应该被用来获取string来自NegativeSqrt(因为fmt.Sprint通过采用其参数interface{})。
为了说明这一点,请考虑以下示例:
package main
import (
"fmt"
)
type NegativeSqrt float64
func (e NegativeSqrt) Error() string {
return ""
}
func (e NegativeSqrt) String() string {
return ""
}
func check(val interface{}) {
switch val.(type) {
case fmt.Stringer:
fmt.Println("It's stringer")
case error:
fmt.Println("It's error")
}
}
func check2(val interface{}) {
switch val.(type) {
case error:
fmt.Println("It's error")
case fmt.Stringer:
fmt.Println("It's stringer")
}
}
func main() {
var v NegativeSqrt
check(v)
check2(v)
}
执行这个给出:
% go run a.go
It's stringer
It's error
这是因为在 Go 中类型 switch 的行为就像普通 switch 一样,所以case 的 order 很重要。
TA贡献1834条经验 获得超8个赞
因为类型是error,接口error是
type error interface{
Error() string
}
每个人都error必须有一个Error() string方法,但不一定要有一个String() string方法。这就是为什么首先检查Error()方法的逻辑。
TA贡献1830条经验 获得超3个赞
让我扩展 tumdum 的发现,以便更清楚。
我将从一个呼叫跳转到另一个呼叫以展示我们如何进入循环。
我们从练习开始
func (e NegativeSqrt) Error() string { fmt.Printf(".") return fmt.Sprint(e)}
这将我们带到fmt/print.go的第 237 行:
func Sprint(a ...interface{}) string
在函数内部,我们的下一个跳转在第 239 行:
p.doPrint(a, false, false)
我们到达第 1261 行:
func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
在该函数中,我们将使用我们的error
参数跳转到第 1273 行:
prevString = p.printArg(arg, 'v', 0)
我们在第 738 行到达了一个巨大的核心怪物函数:
func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) {
在里面,你可以看到一个大switch case
开关。error
进入该default
部分,因为它被认为是一个非平凡的类型。
这将我们带到第 806 行并调用handleMethods()
:
if handled := p.handleMethods(verb, depth); handled {
我们到达第 688 行:
func (p *pp) handleMethods(verb rune, depth int) (handled bool) {
在该函数内部,在第 724 行,调用Error()
发生,从而完成循环:
p.printArg(v.Error(), verb, depth)
- 3 回答
- 0 关注
- 296 浏览
添加回答
举报