最近我被问到一个问题,即Golang和Java之间关于界面的区别是什么?
我知道有一些'句法糖水平'差异,我感兴趣的是底层的东西,比如Golang和Java如何实现界面?最大的区别是什么?哪一个更有效率?为什么呢?
有人可以发布有关此主题的博客链接或源代码吗?源代码更好。
感谢。
答案 0 :(得分:4)
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查找。
有关详细信息,请参阅: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