静态类型定义与动态查找

时间:2014-04-10 22:53:56

标签: go

在书上The Go Programming Language Phrasebook说:

  

如果您需要演奏,则可以静态使用   键入定义并避免动态查找。   如果您需要灵活性,那么您可以使用   接口的后期绑定机制

有人可以解释一下"静态类型定义"和"动态查找"是用于Go的方法和功能吗?

2 个答案:

答案 0 :(得分:2)

想象一下,我们有以下代码:

type A struct {}

func (a A) Foo() {
    fmt.Println("Foo called")
}

type I interface {
    Foo()
}

我现在可以创建A类型的变量并调用此方法:

a := A{}
a.Foo()

编译器知道变量的静态类型,因此知道方法调用引用A.Foo方法。因此它可以编译上面的代码以使用对A.Foo的直接调用,这将与普通函数调用一样快。

如果我们使用类型为I的变量,则情况就不同了:

var i I = A{}
i.Foo()

变量i可以包含任何具有Foo方法的类型。在这种特殊情况下,它保持A值,但在编译时不一定知道这一点。因此,编译器生成代码来检查i动态类型,查找关联的Foo方法,最后调用该方法。这种调度形式比第一种形式慢,但是代码对于实现接口的任何类型都有效。

这类似于C ++在虚拟和非虚拟方法之间的区别,除了在定义时为方法修复的调度类型,它取决于您在Go中使用的变量类型。

答案 1 :(得分:1)

本书在使用静态类型时所指的是使用非接口类型:

func Foo(v int, s string) { ... }

另一个选项是使用界面:

func Bar(a interface{}, b interface{}) { ... }

因为使用第一个选项,Go将在编译时知道函数将检索哪种类型的值(在这种情况下为int和string),它将专门为这些类型编译代码。

使用第二个选项,您必须在运行时使用反射才能知道接口中包含的值。这有点开销,但它允许您将不同类型的值作为参数传递给函数,从而更加动态。

进一步阅读: Laws of Reflection in Go