MST

星途 面试题库

面试题:Go接口数据结构之方法集

在Go语言中,接口类型的变量有其对应的方法集。请解释一个实现了接口的结构体类型,其值和指针的方法集有何不同,并举例说明这种差异对接口调用的影响。
34.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 结构体值和指针的方法集差异
    • 结构体值的方法集:结构体值的方法集只包含接受者为值类型的方法。例如:
package main

import "fmt"

type Animal struct {
    Name string
}

func (a Animal) Speak() {
    fmt.Printf("%s says hello\n", a.Name)
}

这里 Animal 结构体值的方法集包含 Speak 方法,因为 Speak 方法的接受者是 Animal 类型(值类型)。

  • 结构体指针的方法集:结构体指针的方法集包含接受者为值类型和指针类型的方法。例如:
package main

import "fmt"

type Animal struct {
    Name string
}

func (a Animal) Speak() {
    fmt.Printf("%s says hello\n", a.Name)
}

func (a *Animal) Move() {
    fmt.Printf("%s is moving\n", a.Name)
}

对于 *Animal 指针类型的方法集,既包含接受者为 Animal 值类型的 Speak 方法,也包含接受者为 *Animal 指针类型的 Move 方法。 2. 对接口调用的影响

  • 接口值由结构体值初始化:当接口值由结构体值初始化时,只能调用结构体值方法集中的方法。例如:
package main

import "fmt"

type Animal interface {
    Speak()
}

type Dog struct {
    Name string
}

func (d Dog) Speak() {
    fmt.Printf("%s the dog barks\n", d.Name)
}

func main() {
    var a Animal
    dog := Dog{Name: "Buddy"}
    a = dog
    a.Speak()
    // 下面这行代码会编译错误,因为接口值a由结构体值初始化,
    // 而结构体值方法集不包含接受者为指针类型的方法
    // var mover interface { Move() }
    // mover = dog
    // mover.Move()
}
  • 接口值由结构体指针初始化:当接口值由结构体指针初始化时,可以调用结构体指针方法集中的所有方法(包括接受者为值类型和指针类型的方法)。例如:
package main

import "fmt"

type Animal interface {
    Speak()
    Move()
}

type Dog struct {
    Name string
}

func (d Dog) Speak() {
    fmt.Printf("%s the dog barks\n", d.Name)
}

func (d *Dog) Move() {
    fmt.Printf("%s the dog is moving\n", d.Name)
}

func main() {
    var a Animal
    dog := &Dog{Name: "Buddy"}
    a = dog
    a.Speak()
    a.Move()
}

在这个例子中,由于接口值 a*Dog 指针初始化,所以可以调用 SpeakMove 方法。如果接口值由 Dog 结构体值初始化,就只能调用 Speak 方法,不能调用 Move 方法。