为什么不使用%v打印int和string

为什么不使用%v打印int和string,string,go,formatting,printf,String,Go,Formatting,Printf,我知道要打印int我们可以使用%d,而string我们可以使用%s 但是我们仍然可以使用%v打印它们。那么,如果我总是使用%v来打印它们呢?如果我这样做,会发生什么问题?不会发生什么不好的事情,但是%d动词指示包以数字形式打印(使用基数10),而%v动词意味着使用可以覆盖的默认格式 请参见此示例: type MyInt int func (mi MyInt) String() string { return fmt.Sprint("*", int(mi), &quo

我知道要打印
int
我们可以使用
%d
,而
string
我们可以使用
%s

但是我们仍然可以使用
%v
打印它们。那么,如果我总是使用
%v
来打印它们呢?如果我这样做,会发生什么问题?

不会发生什么不好的事情,但是
%d
动词指示包以数字形式打印(使用基数10),而
%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)
}
输出(在上尝试):

当使用
%v
动词时,
fmt
包检查值是否实现了接口(它是单个
String()String
方法),如果是,将调用该方法将值转换为
String
(如果指定了标志,可以进一步格式化)

格式规则的完整列表在
fmt
的文件包中,引用了相关部分:

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

  • 如果操作数是一个reflect.Value,则该操作数将替换为它所持有的具体值,并继续打印下一条规则

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

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

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

  • 如果操作数实现错误接口,将调用error方法将对象转换为字符串,然后按照谓词(如果有)的要求格式化字符串

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


  • 我发现可能存在使用%v的递归,因为您正在重写的字符串()将被转换为字符串时调用。使用%v inside String()尝试转换a(类型a)时,会触发递归调用。切勿在该类型的字符串()中使用%v。
    2 *2*