为什么Error()优先于String()

时间:2015-05-11 05:05:06

标签: string go

我一直在浏览巡演,我无法弄清楚为什么会这样。

如果您有StringerString() 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

2 个答案:

答案 0 :(得分:8)

仅仅因为这是它的实现方式。 error在实践中更为重要,因此如果error接口已实现,则会打印出来。

记录在案,阅读fmt的包文档:

  

除非使用动词%T和%p打印,否则特殊格式注意事项适用于实现某些接口的操作数。按申请顺序:

     
      
  1. 如果操作数实现了Formatter接口,则会调用它。 Formatter可以很好地控制格式化。

  2.   
  3. 如果%v动词与#flag(%#v)一起使用,并且操作数实现了GoStringer接口,那么将调用它。

  4.         

    如果格式(对于Println等隐式%v)对字符串有效(%s%q%v%x%X),则适用以下两条规则:

         
        
    1. 如果操作数实现错误接口,则将调用Error方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)。

    2.   
    3. 如果操作数实现方法 String()字符串,则将调用该方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)

    4.   

所以error在列表中是3 rd ,而String()只有4 th

答案 1 :(得分:1)

原因很简单:当 fmt 使用其中任何一个打印函数时,它会为每个参数执行一个类型切换以确定应该如何打印,并在该类型中切换case error出现在case Stringer之前。