请考虑以下代码。第一个功能是MessageStr类型的接收器方法。为什么fmt.Println(msgstr)
执行第一个方法而不将方法称为fmt.Println(msgstr.String())
。也是为什么fmt.Println(msgint32)
不执行第二种方法的原因。
package main
import (
"fmt"
)
type MessageStr string
type MessageInt32 int32
func (msgs MessageStr) String() string {
return string("<<" + msgs + ">>")
}
func (msgi MessageInt32) Int32() int32 {
return int32(msgi * 2)
}
func main() {
msgstr := MessageStr("Mastering Go")
// why this outputs <<Mastering Go>>
// without calling the String() method
fmt.Println(msgstr)
msgint32 := MessageInt32(11)
// why this doesn't output 11*2 = 22
fmt.Println(msgint32)
fmt.Println(msgint32.Int32())
}
答案 0 :(得分:3)
调用fmt.Println
时,它会期望一个实现Stringer
接口的对象。 documented如下:
如果操作数实现String()字符串方法,则该方法将是 调用以将对象转换为字符串,然后将其转换为 根据动词要求的格式设置(如果有)
fmt
包还声明了Stringer
接口:
type Stringer interface {
String() string
}
此类对象必须具有不带参数且返回String()
的{{1}}方法。 string
然后调用fmt.Println
方法。这使我们可以为自定义类型定义如何将其打印出来。例如:
String
将打印出
package main
import "fmt"
type Person struct {
name string
age int
}
func (p Person) String() string {
return fmt.Sprintf("%s<%d>", p.name, p.age)
}
func main() {
p := Person{name: "Joe", age: 39}
fmt.Println(p)
}
因为我们已经定制了Joe<39>
对象被转换为字符串的方式。详细信息:
如果您对如何在Person
包中实际发生这种情况的机制感兴趣,请查看fmt
中的handleMethods
方法。