Go 中嵌入结构的奇怪方法调用:理解 String()
在 Go 中,嵌入结构继承其嵌入类型的方法。但是,当多个嵌入类型定义具有相同名称的方法时,就会出现歧义。让我们特别关注 String() 方法来探索这种行为。
在提供的示例代码中:
type Engineer struct { Person TaxPayer Specialization string } type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("name: %s, age: %d", p.Name, p.Age) } type TaxPayer struct { TaxBracket int } func (t TaxPayer) String() string { return fmt.Sprintf("%d", t.TaxBracket) }
当使用 fmt.Println(engineer) 打印 Engineer 结构体时,输出根据嵌入类型中是否存在 String() 方法而变化。
与Person.String():
无Person.String():
没有两个 String()方法:
这些场景突出了 Go 中提升方法的深度规则和歧义解决。然而,问题出现了,为什么当存在多个深度为零的 String() 方法时,在编译时没有检测到歧义性。
不明确的选择器检查:
通常,当尝试使用不明确的选择器调用方法(例如 Engineer.Foo())时,会发生编译时错误。但是,使用名为 String() 的方法不会发生这种情况。
原因:
在未显式调用其 String() 方法的情况下打印值时, fmt.Println函数检查该值是否实现 fmt.Stringer。然后它调用已实现的 String() 方法。由于所有 Go 类型默认都隐式实现 Stringer (https://golang.org/doc/go1.19#fmt),因此任何类型总有一个提升的 String() 方法。
结论:
嵌入结构的方法调用的歧义性是由于深度规则和用于打印的 String() 方法的特殊处理而产生的价值观。通过了解这些规则以及方法提升中的细微差别,开发人员可以避免意外行为并保持 Go 程序中代码的清晰度。
以上是为什么 Go 在编译时不检测嵌入式结构的 String() 方法调用中的歧义?的详细内容。更多信息请关注PHP中文网其他相关文章!