如果我们使用接口,静态(编译时)或动态(运行时),实际上Go中的方法将如何调度。让我们考虑这段代码:
package main
import "fmt"
type ICat interface {
Meow()
Walk()
Run()
}
func NewCat(name string) ICat {
return &cat{
name:name,
}
}
type cat struct {
name string
}
func (c *cat) Meow() {
fmt.Print("Meowwwwwwwww")
}
func (c *cat) Walk() {
fmt.Print("Walk")
}
func (c *cat) Run() {
fmt.Print("Run")
}
type IAnimal interface{
DoSound()
}
type animal struct {
cat ICat
}
func New() IAnimal {
return &animal{
cat:NewCat("bobby"),
}
}
func (a *animal) DoSound() {
a.cat.Meow()
}
func main() {
i := New()
i.DoSound()
}
去游乐场:https://play.golang.org/p/RzipDT6FAC9
实际上是如何调度那些接口中定义的那些方法的?我使用这种开发方式来实现接口分离以及数据和行为之间关注点的分离。我的另一个担心是性能。有人说它是在编译时静态调度的,而有人说它是在运行时动态调度的。
我们在编译时无法知道接口值的动态类型,因此通过接口进行的调用必须使用dynamic dispatch。代替直接调用,编译器必须生成代码以从类型描述符中获取方法的地址,然后对该地址进行间接调用。