当打印带有实现了String()的嵌套结构的结构时,根据我们的理解,%v
格式将打印“意外”值。
下面是代码段。
package main
import (
"fmt"
)
type Inner struct {
}
type A struct {
Inner
FieldA string
}
func (i Inner) String() string {
return "anything"
}
func main() {
myA := A{FieldA: "A"}
fmt.Printf("%v", myA)
}
我们希望输出为
{任何A}
但是实际结果是
任何东西
为什么会这样?似乎FieldA
被忽略了吗?更令人困惑的是,如果我们有两个嵌套结构,其中两个结构都实现了String(),则将得到预期的输出。
package main
import (
"fmt"
)
type Inner struct {
}
type InnerAgain struct {
}
type A struct {
Inner
InnerAgain
FieldA string
}
func (i Inner) String() string {
return "anything"
}
func (i InnerAgain) String() string {
return "nothing"
}
func main() {
myA := A{FieldA: "A"}
fmt.Printf("%v", myA)
}
输出为
{什么都没有A}
...
答案 0 :(得分:6)
由于您嵌入Inner
,因此您固有的所有属性-包括String()-函数。因此%v
实际上是在呼叫Inner.String()
从文档(https://golang.org/pkg/fmt/):
- 如果操作数实现方法
String() string
,则该方法将 被调用以将对象转换为字符串,然后将其 根据动词的要求进行格式化(如果有)。
答案 1 :(得分:1)
因为fmt
软件包将%v
的规则表示为:
如果格式(对于Println等而言是隐含的%v)对于字符串(%s%q%v%x%X)有效,则以下两个规则适用:
如果操作数实现了error接口,则将调用Error方法将对象转换为字符串,然后根据动词的要求对其进行格式化(如果有)。
如果操作数实现String()字符串方法,则将调用该方法将对象转换为字符串,然后将根据动词的要求对其进行格式化(如果有)。
因此,%v
实际上将String()
方法用于更严格的参数。