golang interface的eface和iface
在Go语言的内部实现中,接口(interface)有两种不同的底层表示形式:eface
和 iface
。这两种结构用于支持空接口(interface{}
)和具体类型的接口。了解它们的区别有助于更深入地理解Go语言的接口机制。
eface (empty face)
- 定义:
eface
是 Go 用来表示空接口(interface{}
)的底层数据结构。 - 组成:
_type
:一个指向类型信息的指针,描述了存储在接口中的具体类型。data
:一个指向数据的指针,指向实际存储的数据。
对于空接口来说,它不包含任何方法,所以只需要知道存储的是什么类型的数据以及数据本身即可。eface
的设计非常简单,只包含这两个字段。
示例
var i interface{} = "hello"
在这个例子中,i
是一个空接口,它的底层实现使用了 eface
结构来存储字符串 "hello"
的类型信息和值。
iface (interface face)
- 定义:
iface
是 Go 用来表示带有方法集的具体接口类型的底层数据结构。 - 组成:
- 类似于
eface
,它也包含了_type
和data
字段。 - 此外,
iface
还包含了一个方法表(method table),该表列出了接口所要求的所有方法,并为每个方法提供了一个调用这些方法的入口点。
- 类似于
iface
结构更为复杂,因为它不仅需要记录存储的数据和其类型,还需要能够通过接口调用相应的方法。
示例
type Speaker interface {
Speak() string
}
type Person struct {
Name string
}
func (p Person) Speak() string {
return "Hello, my name is " + p.Name
}
var s Speaker = Person{Name: "Alice"}
在这个例子中,s
是一个实现了 Speaker
接口的变量,它的底层实现使用了 iface
结构。iface
不仅保存了 Person
类型的信息和具体的 Person
实例,还维护了 Speak
方法的调用信息。
总结
eface
用于表示空接口,只包含类型信息和数据指针。iface
用于表示具体类型的接口,除了类型信息和数据指针之外,还包括了方法表,以便可以调用接口规定的方法。
这两者都是 Go 语言内部实现细节的一部分,通常开发者不需要直接与它们打交道。然而,理解它们的工作原理可以帮助更好地掌握Go语言中接口的工作方式,尤其是在性能优化或调试时。
多用组合、少用继承
基于接口而非实现进行编程