面试题答案
一键面试- 结构体值和指针的方法集差异
- 结构体值的方法集:结构体值的方法集只包含接受者为值类型的方法。例如:
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
指针初始化,所以可以调用 Speak
和 Move
方法。如果接口值由 Dog
结构体值初始化,就只能调用 Speak
方法,不能调用 Move
方法。