Golang中组合(composition)的性能表现为何如此?

Golang中组合(composition)的性能表现为何如此?

package main

import (
"fmt"
)

type aki float64

func(a aki) String() string {
return fmt.Sprintf("%.2f C", a)
}

type di struct {
aki
name string
}

func main() {
ak := aki(5)
fmt.Println(ak)
d := di{7, "daria"}
fmt.Println(d)
}

为什么当我执行 fmt.Println(d) 时没有打印 name 字段,我必须显式地写 d.name 才能打印出 “daria”


更多关于Golang中组合(composition)的性能表现为何如此?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复
func (d di) String() string {
    return fmt.Sprintf("%s %s", d.aki, d.name)
}

更多关于Golang中组合(composition)的性能表现为何如此?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果某些方法或字段在 di 上不可用,它们将被转发到 aki,由于您没有为 di 实现 String() 方法,因此会使用 aki 的方法。

在Go语言中,当使用组合(composition)时,嵌入类型的方法会被提升到外层类型中。在你的代码中,di 结构体嵌入了 aki 类型,因此 akiString() 方法被提升为 di 的方法。

当调用 fmt.Println(d) 时,fmt 包会检查 di 是否实现了 Stringer 接口(即是否有 String() string 方法)。由于 akiString() 方法被提升,di 也满足 Stringer 接口,所以会调用这个 String() 方法而不是使用默认的格式化输出。

akiString() 方法只返回 aki 字段的格式化字符串,没有包含 name 字段的信息。这就是为什么 fmt.Println(d) 只显示温度值而没有显示名称的原因。

如果你希望打印完整的 di 结构体信息,有几种解决方案:

  1. di 实现自定义的 String() 方法
func (d di) String() string {
    return fmt.Sprintf("{%v %s}", d.aki, d.name)
}
  1. 使用默认的结构体格式化(不实现 String() 方法):
// 移除 aki 的 String() 方法,或者使用 fmt.Printf 的 %+v 格式
fmt.Printf("%+v\n", d)
  1. 显式访问字段
fmt.Println(d.aki, d.name)

修改后的完整示例:

package main

import (
    "fmt"
)

type aki float64

func (a aki) String() string {
    return fmt.Sprintf("%.2f C", a)
}

type di struct {
    aki
    name string
}

// 为 di 实现自定义 String() 方法
func (d di) String() string {
    return fmt.Sprintf("Temperature: %v, Name: %s", d.aki, d.name)
}

func main() {
    ak := aki(5)
    fmt.Println(ak) // 输出: 5.00 C
    
    d := di{7, "daria"}
    fmt.Println(d) // 输出: Temperature: 7.00 C, Name: daria
}

这是Go语言组合特性的正常行为,方法提升机制使得嵌入类型的方法对外层类型可用,但有时需要根据具体需求实现适当的方法重写。

回到顶部