go语言中的指针接收器和值接收器的初始化问题

128 阅读2分钟
  1. 值接收器: 当方法为值接收器时,它会在方法的每次调用时都操作结构体的一个副本。这意味着对结构体字段的任何修改都不会反映到原始结构体上。
type Dog struct{}
func (d Dog) Eat() {}
  1. 指针接收器: 当方法为指针接收器时,它直接作用于原始的结构体实例上,允许方法内部对结构体的修改影响到原始数据。
type Dog struct{}
func (d *Dog) Eat() {}

下面有四个示例,

  • 示例一和示例三是值接收器
  • 示例二和示例四是值接收器
  • 示例一和示例二是值初始化
  • 示例三和示例四是指针初始化

示例一 正常

type Animals interface {
    Eat()
}
type Dog struct{}

func (d Dog) Eat() {}

func main() {
    var a Animals = Dog{}
    a.Eat()
}

示例二 报错

type Animals interface {
    Eat()
}
type Dog struct{}

func (d *Dog) Eat() {}

func main() {
    var a Animals = Dog{}
    a.Eat()
}

image.png 示例三 正常

type Animals interface {
    Eat()
}
type Dog struct{}

func (d Dog) Eat() {}

func main() {
    var a Animals = &Dog{}
    a.Eat()
}

示例四 正常

type Animals interface {
    Eat()
}
type Dog struct{}

func (d *Dog) Eat() {}

func main() {
    var a Animals = &Dog{}
    a.Eat()
}

通过上面的测试,发现 指针接收器通过值初始化会报错

执行go build -gcflags -S main.go可以看到程序的汇编代码

接下来看看实例一的汇编代码,示例一是值接收器,但是在汇编代码中是有对指针接收器的方法的 image.png

说明值接收器的方法会默认添加到指针接收器上一份

指针接收器的方法不会给值接收器添加

结论

  • 值接收器的方法可以,值类型和指针类型都可以调用,因为会给指针接收器也添加上方法
  • 指针接收器的方法不能通过值类型实例直接调用,因为值接收器上没有接口方法,这会涉及到类型不匹配的问题。