为什么%v为嵌套结构打印意外值?

Pix*_*ech -2 go

当使用嵌套结构打印具有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)
}
Run Code Online (Sandbox Code Playgroud)

我们期望产量

{任何东西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)
}
Run Code Online (Sandbox Code Playgroud)

输出是

{什么都不是啊}

...

maj*_*aja 6

因为你是嵌入的Inner,所以你固有它的所有属性 - 包括String() - 函数.所以%v实际上是在呼唤Inner.String()

从文档(https://golang.org/pkg/fmt/):

  1. 如果操作数实现方法String() string,则将调用该方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有).

  • 并且要扩展,如果你有两个嵌入式结构,两个都有一个String()函数,那么在嵌入结构上调用`String()`是不明确的,因此那些String()方法不会被提升.这导致嵌入结构(`A`)不再实现`fmt.Stringer`接口,因此`fmt`回退到默认的打印格式,这就是为什么你在这种情况下得到完整的结构. (2认同)