我知道打印 int
可以使用 %d
,而 string
可以使用 %s
,
但我们仍然可以使用 %v
来打印它们。那么如果我总是使用 %v
来打印它们会有什么问题呢?
我知道打印 int
可以使用 %d
,而 string
可以使用 %s
,
但我们仍然可以使用 %v
来打印它们。那么如果我总是使用 %v
来打印它们会有什么问题呢?
不会发生任何不好的事情,但是%d
动词指示fmt
包将其作为数字(使用十进制)打印出来,而%v
动词表示使用默认格式,该格式可以被覆盖。
看这个例子:
type MyInt int
func (mi MyInt) String() string {
return fmt.Sprint("*", int(mi), "*")
}
func main() {
var mi MyInt = 2
fmt.Printf("%d %v", mi, mi)
}
输出结果(在Go Playground上进行尝试):
2 *2*
%v
动词时,fmt
包会检查该值是否实现了fmt.Stringer
接口(单个String() string
方法),如果是,则调用该方法将该值转换为string
(如果指定了标志,则可能进一步格式化)。fmt
包文档中,引用相关部分:
除非使用%T和%p动词打印,否则对于实现某些接口的操作数,应用特殊的格式化考虑。按应用顺序:
如果操作数是reflect.Value,则将其替换为它所持有的具体值,并继续打印下一个规则。
如果操作数实现了Formatter接口,则将调用它。Formatter提供了格式化的精细控制。
如果使用#标志(%#v)并且操作数实现了GoStringer接口,则将调用该接口。
如果格式(对于Println等隐式为%v)对于字符串有效(%s %q %v %x %X),则适用以下两个规则:
如果操作数实现了error接口,则将调用Error方法将对象转换为字符串,然后按所需的动词(如果有)格式化。
如果操作数实现了String() string方法,则将调用该方法将对象转换为字符串,然后按所需的动词(如果有)格式化。