看来已经解释了directly https://github.com/golang/go/blob/2ed57a8cd86cec36b8370fb16d450e5a29a9375f/src/pkg/fmt/print.go#L639是 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() http://golang.org/src/fmt/print.go?s=6663:6699#L714 or String() http://golang.org/src/fmt/print.go?s=6663:6699#L720叫做。
这句话的意思就是首先错误.Error() http://golang.org/pkg/builtin/#error调用以生成字符串,然后再次处理该字符串并将其打印为字符串。
Whether error
有方法String
在这里无关紧要。问题是为什么NegativeSqrt
使用一种方法打印,而不使用另一种方法打印。类型NegativeSqrt
两者都实现fmt.Stringer
and error
接口,所以它取决于实现fmt
封装应该使用哪个接口来获取string
from NegativeSqrt
(since fmt.Sprint http://golang.org/src/fmt/print.go?s=6663:6699#L237其参数为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 一样,所以案件顺序很重要 https://golang.org/doc/effective_go.html#switch.