通常在尝试打印 结构时 ,我们会使用%v来显示结构的所有数据。它将打印结构中每个字段的默认格式。
但是最近我们在使用嵌套结构打印结构时发现了一个奇怪的行为,该结构具有一个 String()字符串 , %v
格式根据我们的理解打印出“意外”输出。
我们先看看示例代码段。
Inner
FieldA string}func (i Inner) String() string { return "anything"}func main() {
myA := A{FieldA: "A"}
fmt.Printf("%v", myA)}
我们期望产量
{任何东西A}
但实际结果是
什么
这没有意义,对吧?这似乎 FIELDA 如果被忽略 的字符串()字符串 是为实现 内部 结构类型。
根据我们的理解,struct A类型有两个字段: Inner 和 FieldA,在打印值时,它将循环遍历字段并使用其默认格式进行打印。所以Inner应该调用它的String(),而FieldA将打印它的字符串值。但是,上述输出让我们怀疑我们的理解。
仔细研究一下这些文档之后,它就有了以下规则。
● 如果格式(对于Println等隐式%v)对字符串有效(%s%q%v%x%X),则适用以下两个规则:
● 如果操作数实现了错误接口,则将调用Error方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)。
如果操作数实现方法String()字符串,则将调用该方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有)。
由于 Inner 是一个操作数,它实现了 String()字符串 方法,该方法被视为 Stringer 接口,因此在打印时会调用它。这解释了我们实际看到的输出。下面实际上是Go中源代码的一部分。
handled = true defer p.catchPanic(p.arg, verb)
p.fmtString(v.Error(), verb) return case Stringer:
handled = true defer p.catchPanic(p.arg, verb)
p.fmtString(v.String(), verb) return }}
现在如果我们在A中有两个嵌套结构并且它们都实现了 String()字符串 怎么办?
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)}
输出是我们最初的预期
{什么都不是啊}
上面输出的原因是调用String()是不明确的,因此它将回退遍历所有字段并以默认格式获取它们的值。
请注意Go提供的上述行为,以便在使用%v格式在日志中打印struct时不会错过一些重要数据。
原文发布时间为:2018-11-11
本文来自云栖社区合作伙伴“Golang语言社区”,了解相关信息可以关注“Golang语言社区”。