Stringer
是Golang
的fmt
包中的一个类型。
Stringer
由任何具有String
方法的值来实现。
实现Stringer
的类型与字符串的打印方式相同。Stringer
会返回一个字符串。
type Stringer
type Stringer interface { String() string }
让我们看一个例子,我们有一个结构,我们试图使用fmt
包中的Print
来打印它,但没有实现Stringer
。
例子1:
package main import "fmt" type Person struct { ID int Name string Age int } func main() { var p = Person{ID: 1, Name: "Tony", Age: 25} fmt.Println(p) }
我们可以看到,它打印了该结构的每个字段的值。
{1 Tony 25}
例子2:
package main import "fmt" type Person struct { ID int Name string Age int } func main() { var p = Person{ID: 1, Name: "Tony", Age: 25} fmt.Println(p) } func (p Person) String() string { return fmt.Sprintf("Person Type\nID: %d\nName: %s\nAge: %d", p.ID, p.Name, p.Age) }
在这个例子中,Person
结构实现了Stringer
。String()
返回字符串。
Person Type ID: 1 Name: Tony Age: 25
在那个String()
方法中,我们已经返回了一个自定义的字符串。所以每当我们试图使用fmt
包打印Person
类型时,它将检查该类型是否实现了Stringer
。如果实现了,它将打印String()
方法返回的字符串。
重要说明:
String()
方法的接收器类型很重要。
我们知道,我们可以只用数值来调用指针接收方法,但是对于String()
方法,我们不能这样做。
原因是,fmt
包将使用String()
方法来打印我们的类型(如果我们的类型实现了Stringer
接口)。所以每当我们试图用fmt
包的函数打印我们的类型时,它就会断定该类型是否实现了String()
方法。通过这样做,很明显,用值调用的值接收器会通过,用地址值调用的指针接收器会通过,但用值调用的指针接收器会失败。
比如:
package main import "fmt" type Person struct { ID int Name string Age int } func main() { var p = Person{ID: 1, Name: "Tony", Age: 25} fmt.Println(p) } func (p *Person) String() string { return fmt.Sprintf("Person Type\nID: %d\nName: %s\nAge: %d", p.ID, p.Name, p.Age) }
{1 Tony 25}
在输出中,我们可以清楚地看到,fmt
包做了类型断言,所以只有实现了Stringer
类型的类型才会使用我们的自定义字符串打印出来。
我们打印一下类型看看:
fmt.Printf("type of &l: %T\n", &p) fmt.Printf("type of l: %T\n", p)
type of &l: *main.Person type of l: main.Person
当我们使用fmt
包中的打印函数进行打印时,Stringer
非常有用,我们需要对我们的类型进行自定义表示。