我一直在浏览巡演,我无法弄清楚为什么会这样。
如果您有Stringer
(String() string
),fmt
将使用该方法打印到控制台。与https://tour.golang.org/methods/6
但是,如果您添加Error() string
,则会调用此方法而不是String() string
。
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p *Person) String() string {
return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}
func (p *Person) Error() string {
return fmt.Sprintf("Failed")
}
func main() {
a := &Person{"Arthur Dent", 42}
z := &Person{"Zaphod Beeblebrox", 9001}
fmt.Println(a, z)
}
结果:
失败失败
我不明白为什么fmt.Println
使用Error
代替String
。
答案 0 :(得分:8)
仅仅因为这是它的实现方式。 error
在实践中更为重要,因此如果error
接口已实现,则会打印出来。
记录在案,阅读fmt
的包文档:
除非使用动词%T和%p打印,否则特殊格式注意事项适用于实现某些接口的操作数。按申请顺序:
如果操作数实现了Formatter接口,则会调用它。 Formatter可以很好地控制格式化。
- 醇>
如果%v动词与#flag(%#v)一起使用,并且操作数实现了GoStringer接口,那么将调用它。
如果格式(对于Println等隐式%v)对字符串有效(%s%q%v%x%X),则适用以下两条规则:
如果操作数实现错误接口,则将调用Error方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)。
- 醇>
如果操作数实现方法 String()字符串,则将调用该方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)
所以error
在列表中是3 rd ,而String()
只有4 th 。
答案 1 :(得分:1)
原因很简单:当 fmt 使用其中任何一个打印函数时,它会为每个参数执行一个类型切换以确定应该如何打印,并在该类型中切换case error
出现在case Stringer
之前。