面试题答案
一键面试- 方法集与结构体指针和非指针接收器的关系:
- 非指针接收器:当方法使用非指针接收器时,该方法集同时属于结构体类型和结构体指针类型。例如:
package main
import "fmt"
type Dog struct {
Name string
}
func (d Dog) Bark() {
fmt.Printf("%s is barking\n", d.Name)
}
这里Bark
方法使用非指针接收器Dog
,Dog
类型和*Dog
类型都拥有Bark
方法。
func main() {
myDog := Dog{Name: "Buddy"}
myDog.Bark()
dogPtr := &myDog
dogPtr.Bark()
}
- 指针接收器:当方法使用指针接收器时,该方法集仅属于结构体指针类型。例如:
package main
import "fmt"
type Cat struct {
Name string
}
func (c *Cat) Meow() {
fmt.Printf("%s is meowing\n", c.Name)
}
这里Meow
方法使用指针接收器*Cat
,只有*Cat
类型拥有Meow
方法。
func main() {
myCat := Cat{Name: "Whiskers"}
// myCat.Meow() // 这行代码会报错,因为Cat类型没有Meow方法
catPtr := &myCat
catPtr.Meow()
}
- 接口最佳实践:
- 原则:如果方法需要修改接收者的状态,使用指针接收器;如果方法不需要修改接收者的状态,从一致性角度考虑,也可以使用指针接收器,这样所有方法集都统一在指针类型上,方便接口的实现和使用。
- 示例:
package main
import "fmt"
// 定义一个动物接口
type Animal interface {
Speak()
}
type Dog struct {
Name string
}
func (d *Dog) Speak() {
fmt.Printf("%s is barking\n", d.Name)
}
type Cat struct {
Name string
}
func (c *Cat) Speak() {
fmt.Printf("%s is meowing\n", c.Name)
}
func main() {
var a Animal
myDog := &Dog{Name: "Buddy"}
a = myDog
a.Speak()
myCat := &Cat{Name: "Whiskers"}
a = myCat
a.Speak()
}
在这个示例中,Dog
和Cat
结构体都使用指针接收器实现了Animal
接口,这样无论是Dog
还是Cat
的实例,都可以统一通过Animal
接口调用Speak
方法,实现了接口使用的一致性和最佳实践。