在书上The Go Programming Language Phrasebook说:
如果您需要演奏,则可以静态使用 键入定义并避免动态查找。 如果您需要灵活性,那么您可以使用 接口的后期绑定机制
有人可以解释一下"静态类型定义"和"动态查找"是用于Go的方法和功能吗?
答案 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