静态类型定义与动态查找

huangapple go评论75阅读模式
英文:

Statically typed definitions vs dynamic lookup

问题

在书籍《The Go Programming Language Phrasebook》中提到:

> 如果你需要性能,那么你可以使用静态类型定义并避免动态查找。
> 如果你需要灵活性,那么你可以使用接口的后期绑定机制。

有人可以解释一下在Go语言中,方法和函数中的"静态类型定义"和"动态查找"是什么意思吗?

英文:

On the book The Go Programming Language Phrasebook said:

> If you require performance, then you can use statically
> typed definitions and avoid the dynamic lookup.
> If you require flexibility, then you can use the
> late binding mechanism of interfaces

Can someone explain me what "statically typed definitions" and "dynamic lookup" are for methods and functions in Go?

答案1

得分: 2

假设我们有以下代码:

type A struct {}

func (a A) Foo() {
    fmt.Println("调用了Foo")
}

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中,分派的类型取决于您在变量中使用的类型,而不是在方法定义时固定的。

英文:

Imagine that we have the following code:

type A struct {}

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

type I interface {
    Foo()
}

I can now create a variable of type A and call this method:

a := A{}
a.Foo()

The compiler knows the static type of the variable, so knows that the method call refers to the A.Foo method. So it can compile the above code to use a direct call to A.Foo, which will be as fast as a normal function call.

If instead we use a variable of type I, things are different:

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

The variable i can hold any type that has a Foo method. In this particular case it is holding an A value, but won't necessarily know this at compile time. So instead the compiler generates code to check the dynamic type of i, look up the associated Foo method and finally call that method. This form of dispatch is slower than the first, but has the benefit the code will work for any type implementing the interface.

This is similar to C++'s distinction between virtual and non-virtual methods, except rather than the type of dispatch being fixed for a method at its definition, it depends on the type of variable you use in Go.

答案2

得分: 1

当书中提到使用静态类型时,它指的是使用非接口类型:

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

另一种选择是使用接口:

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

因为在第一种选项中,Go 在编译时会知道函数将获取什么类型的值(在这种情况下是int和string),它会专门为这些类型编译代码。

而在第二种选项中,你将不得不在运行时使用反射来了解接口中包含的值。这会增加一些开销,但它允许你将不同类型的值作为参数传递给函数,从而更具动态性。

进一步阅读:Go中的反射法则

英文:

What the book refers to when it says using static types is using non interface types:

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

The other option is using interface:

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

Because with the first option, Go will know at compile time what type of value the function will retrieve (int and string in this case), it will compile the code specifically for those types.

With the second option, you will have to use reflection at runtime in order to know the values contained in the interfaces. This is a bit of overhead, but it allows you to pass different types of values as parameters to the function, thus being more dynamic.

Further reading: Laws of Reflection in Go

huangapple
  • 本文由 发表于 2014年4月11日 06:53:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/23000513.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定