第16节 Go中的接口

36 阅读2分钟

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 结构体需要扩展功能时,同时不希望去破坏继承关系,则可以去实现某个接口来完成功能扩展
  • 继承主要解决了代码的复用性,接口主要是定义好对象行为;所以接口比继承更加灵活