Go和Java之间关于界面的区别是什么?

时间:2016-10-08 13:06:26

标签: java go interface

最近我被问到一个问题,即Golang和Java之间关于界面的区别是什么?

我知道有一些'句法糖水平'差异,我感兴趣的是底层的东西,比如Golang和Java如何实现界面?最大的区别是什么?哪一个更有效率?为什么呢?

有人可以发布有关此主题的博客链接或源代码吗?源代码更好。

感谢。

1 个答案:

答案 0 :(得分:4)

Russ Cox的

Go Data Structures: Interfaces

  

Go的接口 - 静态,在编译时检查,在被询问时是动态的   对于
  Go的界面让你可以像纯粹一样使用鸭子打字   像Python这样的动态语言,但仍然有编译器捕获明显   像传递具有Read方法的对象的int那样的错误   预期,或者像使用错误的数字调用Read方法   参数。
  但是,接口并不局限于静态检查。你可以检查一下   动态地确定特定接口值是否具有附加值   方法。

     

界面值
  使用方法的语言通常属于两个阵营之一:准备   静态地(例如在C ++和Java中)所有方法调用的表,或者做   每次调用时查找方法(如Smalltalk及其许多模仿者,   包括JavaScript和Python)并添加花哨的缓存来实现   呼叫高效。 Go位于两者之间:它有方法表   但是在运行时计算它们。我不知道Go是否是第一个   使用这种技术的语言,但它肯定不是一个普通的语言   接口值表示为给出指针的双字对   有关存储在接口中的类型和指向的信息   相关数据。将b分配给类型的接口值   Stringer设置界面值的两个单词。

     

界面值中的第一个单词指向我所说的   接口表或itable(发音为i-table;在运行时中   源)。 itable从一些关于类型的元数据开始   涉及然后成为函数指针的列表。请注意   itable对应于接口类型,而不是动态类型   接口值中的第二个字指向实际数据   这个案例是b。

的副本      

Go的动态类型转换意味着它不合理   编译器或链接器预先计算所有可能的itables:也有   许多(界面类型,具体类型)对,并且大多数都不需要。   相反,编译器为每个生成类型描述结构   具体类型如Binary或int或func(map [int] string)。除其他外   元数据,类型描述结构包含一个列表   由该类型实现的方法。同样,编译器生成一个   (不同的)每种接口类型的类型描述结构   斯金格;它也包含一个方法列表。接口运行时   通过查找界面中列出的每个方法来计算itable   具体类型的方法表中的类型方法表。运行时   在生成之后缓存itable,以便这种对应关系   只需计算一次。

     

方法查询效果
  Smalltalk和跟随它的许多动态系统执行一个   每次调用方法时都会查找方法。对于速度,很多   实现通常在每个调用站点使用简单的单项缓存   在指令流本身。在多线程程序中,这些   必须谨慎管理缓存,因为多个线程可以在   同一个呼叫站点。即使比赛一直如此   避免,缓存最终会成为内存争用的来源。

     

因为Go具有静态类型的提示以与动态一起使用   方法查找,它可以将查询从调用站点移回   值存储在界面中的时间点。

How does Go interface dispatch work?

  

接口变量上的方法分派与vtable相同   调度。
  第一次具体类型命中接口类型时,它会构建一个   指向vtable的哈希表条目。第二次及以后   相同类型的赋值将执行更便宜的哈希查找   找到vtable。但是方法调度本身总是如此   相当于vtable查找。

规格:Interface types

有关详细信息,请参阅:Go: What's the meaning of interface{}?

这里,Go中两个有趣的接口用例: Why are interfaces needed in Golang?

错误类型是接口类型:How to compare Golang error objects

计算4种不同形状的面积:圆形,方形,矩形和三角形:
Explain Type Assertions in Go

在Go中你不需要像Java关键字implements那样特殊的东西来实现一个接口,在Go中你的类型只有具有正确签名的方法就足够了。

以下是代码(在The Go Playground上试用):

package main

import "fmt"

type Work struct {
    Name string
}

func (t Work) String() string {
    return "Stringer called."
}

func main() {
    w := Work{"Hi"}
    fmt.Println(w)
}

输出:

Stringer called.

规范:type Stringer,并参阅source

type Stringer interface {
        String() string
}
  

Stringer是由任何具有String方法的值实现的   定义该值的“本机”格式。使用String方法   将作为操作数传递的值打印到任何接受a的格式   字符串或未格式化的打印机,如Print。

另见:

Why can't I assign a *Struct to an *Interface?
Meaning of a struct with embedded anonymous interface?
Embedded Interface
Golang: what's the point of interfaces when you have multiple inheritence