Go语言高级应用-接口 | 青训营

146 阅读1分钟

什么是 interface

Go 语言中的接口声明:

type Human interface {
	Say(s string) error
}

关键字主体为 type xxx interface,紧接着可以在方括号中编写方法集,用于声明和定义该接口所包含的方法集。

举个例子:

type Human interface {
	Say(s string) error
}

type TestA string

func (t TestA) Say(s string) error {
	fmt.Printf("煎鱼:%s\n", s)
	return nil
}

func main() {
	var h Human
	var t TestA
	_ = t.Say("炸鸡翅")
	h = t
	_ = h.Say("烤羊排")
}

我们在上述代码中,声明了一个名为 Human 的 interface,其包含一个 Say 方法。同时我们声明了一个 TestA 类型,也有自己的一个 Say 方法。他们两者的方法入参和出参类型均为一样。

而与此同时,我们在主函数 main 中通过声明和赋值,成功将类型为 TestA 的变量 t 赋给了类型为 Human 的变量 h,也就是说两者只因有了个 Say 方法,在 Go 语言的编译器中就认为他们是 “一样” 的了,这也就是业界中常说的鸭子类型。

 数据结构

通过上面的功能代码一看,似乎 Go 语言非常优秀。一个接口,不同的类型,2 个包含相同的方法,也能够对标到一起。

接口到底是怎么实现的呢?底层数据结构又是什么?带着问题,我们开始深挖细节之路。

在 Go 语言中,接口的底层数据结构在运行时一共分为两类结构体(struct),分别是:

  • runtime.eface 结构体:表示不包含任何方法的空接口,也称为 empty interface。
  • runtime.iface 结构体:表示包含方法的接口。