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

Ari*_*osh 2 string go

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

当你有一个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)
}
Run Code Online (Sandbox Code Playgroud)

结果:

失败失败

我不明白为什么fmt.PrintlnError而不是String.

icz*_*cza 8

仅仅因为这是它的实现方式.一个error是在实践中更重要,所以如果error接口被实现,那将被打印出来.

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

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

  1. 如果操作数实现Formatter接口,则将调用它.Formatter提供格式化的精细控制.

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

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

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

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

所以error是3 就行了,而String()只有4 .

  • 忍者......到处都是忍者! (3认同)