面试题答案
一键面试值类型和指针类型的方法集动态变化情况
- 值类型:
- 对于值类型
T
,其方法集是所有接收者类型为T
的方法。例如:
这里type Person struct { Name string } func (p Person) SayHello() { println("Hello, my name is", p.Name) }
Person
类型的值p
可以调用SayHello
方法,因为SayHello
的接收者是Person
类型。- 当值类型的匿名字段发生变化时,其方法集会动态变化。比如:
这里type Animal struct { Name string } func (a Animal) Speak() { println("Animal speaks") } type Dog struct { Animal Breed string } func (d Dog) Bark() { println("Dog barks") }
Dog
类型的值既有自己的Bark
方法,也因为匿名字段Animal
而拥有Speak
方法,当Dog
类型的结构发生变化(比如添加或移除匿名字段),其方法集也会相应改变。 - 对于值类型
- 指针类型:
- 对于指针类型
*T
,其方法集包含接收者为*T
和T
的方法。例如:
这里type Counter struct { Value int } func (c Counter) Increment() { c.Value++ } func (c *Counter) Decrement() { c.Value-- }
*Counter
类型的指针pc
既可以调用Increment
方法(虽然接收者是值类型,但指针也能调用),也可以调用Decrement
方法。- 当指针指向的类型结构发生变化时,其方法集会动态变化。比如,如果给
Counter
类型添加一个新方法:
那么func (c Counter) Double() { c.Value = c.Value * 2 }
*Counter
类型的指针就又多了一个可以调用的Double
方法。 - 对于指针类型
方法集变化对方法调用的影响
- 值类型方法集变化影响:
- 当值类型的方法集变化时,该值类型的实例调用方法的能力也会改变。例如上面
Dog
类型,一开始只有Bark
方法,当添加了Animal
匿名字段后,Dog
类型的值就可以调用Speak
方法了。
func main() { var d Dog d.Bark() d.Speak() }
- 当值类型的方法集变化时,该值类型的实例调用方法的能力也会改变。例如上面
- 指针类型方法集变化影响:
- 指针类型方法集变化同样影响其调用方法的能力。例如
Counter
类型添加Double
方法后,*Counter
类型的指针就可以调用Double
方法。
指针类型的方法集变化可能会导致原本不可调用的方法变得可调用,或者原本可调用的方法因为结构变化而失效(比如移除了某个匿名字段导致相关方法从方法集中消失)。func main() { c := &Counter{Value: 10} c.Increment() c.Decrement() c.Double() }
- 指针类型方法集变化同样影响其调用方法的能力。例如