为什么使用 FMT 打印切片.Println(slice) 在 Golang 中是不同的



code A:

package main
import "fmt"
func main() {
    slice := IntSlice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(slice)
}
type IntSlice []int

产出A:

[0 1 2 3 4 5 6 7 8 9]

代码 B:

package main
import "fmt"
func main() {
    slice := IntSlice{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(slice)
}
type IntSlice []int
func (slice IntSlice) Error() string { return "this is called." }

输出 B:

this is called.

为什么这两个代码(A和B)的fmt.Println(slice)行为不同?
或者为什么fmt.Println(slice)自动呼叫slice.Error()

这被记录为fmt行为的一部分(强调我的):

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

  1. 如果操作数是反射。值,操作数将替换为它所持有的具体值,打印继续执行下一个规则。

  2. 如果操作数实现格式化程序接口,则将调用该接口。格式化程序提供对格式的精细控制。

  3. 如果 %v 谓词与 # 标志 (%#v) 一起使用,并且操作数实现了 GoStringer 接口,则将调用该接口。

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

  4. 如果操作数实现错误接口,则将调用 Error 方法将对象转换为字符串,然后根据谓词(如果有)的要求设置该字符串的格式。

  5. 如果操作数实现方法 String() 字符串,则将调用该方法将对象转换为字符串,然后根据谓词(如果有)的要求设置该字符串的格式。

对于复合操作数(

如切片和结构),格式以递归方式应用于每个操作数的元素,而不是整个操作数。因此,%q 将引用字符串切片的每个元素,而 %6.2f 将控制浮点数组每个元素的格式。

fmt包看到slice实现error并打印value.Error(),而不是遍历切片并将格式应用于每个元素。

最新更新