1. 接口的概念
Go中的接口(interface)也是一种数据类型,interface 类型中可以定义一组方法,但是这些方法没有实现。并且 interface 中不能包含任何变量。
1.1 基本语法
type 接口名 interface {
method1(参数列表) 返回值列表
method2(参数列表) 返回值列表
...
}
- 接口中的所有方法都没有方法体
- Go 中的接口不需要显式的实现,只要自定义数据类型变量中包含了接口类型的所有方法,那么这个自定义类型就实现了接口
2. 接口使用细节
- 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型变量
package main
import "fmt"
type DemoInterface interface {
Hello()
}
type A struct {
Name string
}
// 数据类型A实现了 接口 DemoInterface 的方法
func (a A) Hello() {
fmt.Println("say hello interface")
}
func main() {
var a A
// say hello interface
a.Hello()
// 接口数据类型可以指向实现了接口的数据类型变量
var h DemoInterface = a
// 0xc000010250
fmt.Println(&h)
}
- 只能是自定义数据类型才能实现接口,一个自定义数据类型要实现接口,必须实现接口中的所有方法
- 接口中不允许有任何变量
- Go中的接口可以继承,比如 A 接口继承了 B、C 接口,如果此时实现 A 接口,也必须实现 B、C 接口的全部方法
package main
import "fmt"
type B interface {
getB()
}
type C interface {
getC()
}
// 接口 A 继承了接口 B 和 C
type A interface {
B
C
getA()
}
// 结构体 Demo 要实现接口 A B C 的所有方法
type Demo struct {
}
func (d Demo) getB() {
fmt.Println("getB")
}
func (d Demo) getC() {
fmt.Println("getC")
}
func (d Demo) getA() {
fmt.Println("getA")
}
func main() {
var d Demo
d.getA()
d.getB()
d.getC()
}
- interface 类型默认是一个引用类型,如果没有对 interface 初始化,那么会输出 nil;接口类型初始化就是让让它指向实现自己的数据类型变量
- Go中所有数据类型都可以实现空接口,即可以把任何一个变量赋值给空接口
// 空接口的定义
type T interface {
}
3. 实现接口 vs 继承
总的来说:实现接口可以看作是对继承的一种补充
- 当 A 结构体继承了 B 结构体,那么 A 结构体就自动的继承了 B 结构体的字段和方法,并可以直接使用
- 当 A 结构体需要扩展功能时,同时不希望去破坏继承关系,则可以去实现某个接口来完成功能扩展
- 继承主要解决了代码的复用性,接口主要是定义好对象行为;所以接口比继承更加灵活