面试题答案
一键面试方法集与接口实现的联系
- 接口实现时方法集的要求:
- 在Go语言中,一个类型实现一个接口,要求该类型的方法集包含接口中定义的所有方法。
- 对于结构体类型,其方法集分为指针接收器方法集和值接收器方法集。
- 若接口方法使用指针接收器定义,那么只有实现类型的指针类型可以实现该接口;若接口方法使用值接收器定义,实现类型的指针类型和值类型都可以实现该接口。
- 方法集对接口动态调度的影响:
- 当一个接口变量被赋值为不同的实现类型时,Go语言会根据接口变量实际指向的值的动态类型来调用相应的方法。
- 若接口变量存储的是指针类型的值,会在指针类型的方法集中查找方法;若存储的是值类型的值,会在值类型的方法集中查找方法。
代码示例
- 指针接收器对接口实现的影响:
package main
import "fmt"
// 定义一个接口
type Printer interface {
Print()
}
// 定义一个结构体
type Book struct {
Title string
}
// 使用指针接收器为Book定义方法
func (b *Book) Print() {
fmt.Printf("Book Title: %s\n", b.Title)
}
func main() {
var p Printer
book := Book{"Go Programming"}
// 这里必须使用指针,因为接口方法使用指针接收器定义
p = &book
p.Print()
}
在上述代码中,Printer
接口的Print
方法使用指针接收器定义,所以Book
类型的指针才能实现该接口。
- 值接收器对接口实现的影响:
package main
import "fmt"
// 定义一个接口
type Shaper interface {
Area() float32
}
// 定义一个结构体
type Square struct {
side float32
}
// 使用值接收器为Square定义方法
func (s Square) Area() float32 {
return s.side * s.side
}
func main() {
var s Shaper
square := Square{5}
// 这里值类型和指针类型都可以赋值给接口变量
s = square
fmt.Printf("Area of square: %f\n", s.Area())
s = &square
fmt.Printf("Area of square: %f\n", s.Area())
}
在这个例子中,Shaper
接口的Area
方法使用值接收器定义,所以Square
类型的值和指针都能实现该接口,并且在接口动态调度时都能正确调用Area
方法。