Stringer接口结构如下:
type Stringer interface {
String() string
}
作用:
实现了Stringer接口的类型(即有String方法),定义了该类型值的原始显示。当采用任何接受字符的verb(%v %s %q %x %X)动作格式化一个操作数时,或者被不使用格式字符串如Print函数打印操作数时,会调用String方法来生成输出的文本。
int类型实现String()方法
type intExtend int
func (s intExtend) String() string {
return fmt.Sprintf("%d extend", int(s))
}
var i int = 5
var ie intExtend = 5
fmt.Printf("%s\n", i) // %!s(int=5)
fmt.Printf("%s\n", ie) // 5 extend
fmt.Printf("%q\n", i) // \x05
fmt.Printf("%q\n", ie) // 5 extend
fmt.Printf("%v\n", i) // 5
fmt.Printf("%v\n", ie) // 5 extend
fmt.Printf("%x\n", i) // 5 (数值的16进制)
fmt.Printf("%x\n", ie) // 3520657874656e64 ( 等同 fmt.Printf("%x\n","5 extend") )
fmt.Printf("%X\n", i) // 5 (数值的16进制)
fmt.Printf("%X\n", ie) // 3520657874656e64 ( 等同 fmt.Printf("%X\n","5 extend") )
string类型实现String()方法
type stringExtend string
func (s stringExtend) String() string {
//注意 需要用string(s)强制转化下类型,否则会无限递归
return fmt.Sprintf("%s extend", string(s))
}
var s string = "string"
var se stringExtend = "string"
fmt.Printf("%s\n", s) // string
fmt.Printf("%s\n", se) // string extend
fmt.Printf("%q\n", s) // "string"
fmt.Printf("%q\n", se) // "string extend"
fmt.Printf("%v\n", s) // string
fmt.Printf("%v\n", se) // string extend
fmt.Printf("%x\n", s) // 737472696e67 ( 等同 fmt.Printf("%x\n","string") )
fmt.Printf("%x\n", se) // 737472696e6720657874656e64 ( 等同 fmt.Printf("%x\n","string extend") )
fmt.Printf("%X\n", s) // 737472696E67 ( 等同 fmt.Printf("%X\n","string") )
fmt.Printf("%X\n", se) // 737472696E6720657874656E64 ( 等同 fmt.Printf("%X\n","string extend") )
struct类型实现String()方法
type AnimalSelfDefine struct {
Name string
Age int
}
// 实现Stringer接口的方法
func (a AnimalSelfDefine) String() string {
return fmt.Sprintf("%s (%d)", a.Name, a.Age)
}
type Animal struct {
Name string
Age int
}
a := Animal{
Name: "string",
Age: 5,
}
selfDefine := AnimalSelfDefine{
Name: "string",
Age: 5,
}
fmt.Printf("%s\n", a) //{string %!s(int=5)}
fmt.Printf("%s\n", selfDefine) //string (5)
fmt.Printf("%q\n", a) // {"string" '\x05'}
fmt.Printf("%q\n", selfDefine) //"string (5)"
fmt.Printf("%v\n", a) // {string 5}
fmt.Printf("%v\n", selfDefine) // string (5)
fmt.Printf("%x\n", a) // {737472696e67 5}
fmt.Printf("%x\n", selfDefine) //737472696e6720283529 (等同 fmt.Printf("%x\n", "string (5)"))
fmt.Printf("%X\n", a) // {737472696E67 5}
fmt.Printf("%X\n", selfDefine) // 737472696E6720283529 (等同 fmt.Printf("%X\n", "string (5)"))
看上面的测试输出,也可以发现 未实现string()方法的结构体, 在格式输出时,相当于把结构体的每个成员分别格式化,用空格拼接。
其实GO语言内部,复合类型的操作数,如切片和结构体,格式化动作verb递归地应用于其每一个成员,而不是作为整体一个操作数使用。