Golang 中的接口

  • 在Go语言中接口(interface)是一种类型,一种抽象的类型。
  • 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
  • 实现接口的条件
    • 一个对象只要全部实现了接口中的方法,那么就实现了这个接口。
    • 换句话说,接口就是一个需要实现的方法列表。

定义一个Usber接口

定义一个 Usber 接口让 Phone 和 Camera 结构体实现这个接口

//1.接口是一个规范
type Usber interface {
	start()
	stop()
}

//2.如果接口里面有方法的话,必要要通过结构体或者通过自定义类型实现这个接口
type Phone struct {
	Name string
}

//3.手机要实现usb接口的话必须得实现usb接口中的所有方法
func (p Phone) start() {
	fmt.Println(p.Name, "启动")
}
func (p Phone) stop() {
	fmt.Println(p.Name, "关机")
}

func main() {
	p := Phone{
		Name: "华为手机",
	}
	var p1 Usber   //golang中接口就是一个数据类型
	p1 = p       //表示手机实现Usb接口
	p1.start()
	p1.stop()
}
/*
华为手机 启动
华为手机 关机
 */

空接口

  • golang中空接口也可以直接当做类型来使用,可以表示任意类型
  • Golang 中的接口可以不定义任何方法,没有定义任何方法的接口就是空接口。
  • 空接口表示没有任何约束,因此任何类型变量都可以实现空接口。
  • 空接口在实际项目中用的是非常多的,用空接口可以表示任意数据类型。
    空接口作为函数的参数
//空接口作为函数的参数
func show(a interface{}) {
	fmt.Printf("值:%v 类型:%T\n", a, a)
}
func main() {
	show(20)                      // 值:20 类型:int
	show("你好golang")            // 值:你好golang 类型:string
	slice := []int{1, 2, 34, 4}
	show(slice)                     // 值:[1 2 34 4] 类型:[]int
}

切片实现空接口

func main() {
	var slice = []interface{}{"张三", 20, true, 32.2}
	fmt.Println(slice)  // [张三 20 true 32.2]
}

map 的值实现空接口

func main() {
	// 空接口作为 map 值
	var studentInfo = make(map[string]interface{})
	studentInfo["name"] = "张三"
	studentInfo["age"] = 18
	studentInfo["married"] = false
	fmt.Println(studentInfo)
	// [age:18 married:false name:张三]
}

类型断言

  • 一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。
  • 这两部分分别称为接口的动态类型和动态值。
  • 如果我们想要判断空接口中值的类型,那么这个时候就可以使用类型断言
  • 其语法格式:x.(T)
    • x : 表示类型为 interface{}的变量
    • T : 表示断言 x 可能是的类型
func main() {
	var x interface{}
	x = "Hello golang"
	v, ok := x.(string)
	if ok {
		fmt.Println(v)
	}else {
		fmt.Println("非字符串类型")
	}
}

值接收者和指针接收者

值接收者 如果结构体中的方法是值接收者,那么实例化后的结构体值类型和结构体指针类型都可以赋值给接口变量

type Usb interface {
	Start()
	Stop()
}
type Phone struct {
	Name string
}
func (p Phone) Start() {
	fmt.Println(p.Name, "开始工作")
}
func (p Phone) Stop() {
	fmt.Println("phone 停止")
}
func main() {
	phone1 := Phone{
		Name: "小米手机",
	}
	var p1 Usb = phone1      //phone1 实现了 Usb 接口 phone1 是 Phone 类型
	p1.Start()

	phone2 := &Phone{	     //小米手机 开始工作
		Name: "苹果手机",
	}
	var p2 Usb = phone2      //phone2 实现了 Usb 接口 phone2 是 *Phone 类型
	p2.Start()            //苹果手机 开始工作
}

指针接收者如果结构体中的方法是指针接收者,那么实例化后结构体指针类型都可以赋值给接口变量,结构体值类型没法赋值给接口变量。

type Usb interface {
	Start()
	Stop()
}
type Phone struct {
	Name string
}
func (p *Phone) Start() {
	fmt.Println(p.Name, "开始工作")
}
func (p *Phone) Stop() {
	fmt.Println("phone 停止")
}
func main() {
	/*错误写法
	phone1 := Phone{
		Name: "小米手机",
	}
	var p1 Usb = phone1
	p1.Start()
	*/
	//正确写法
	phone2 := &Phone{
		Name: "苹果手机",
	}
	var p2 Usb = phone2 //phone2 实现了 Usb 接口 phone2 是 *Phone 类型
	p2.Start()
	//苹果手机 开始工作
}

一个结构体实现多个接口

type AInterface interface {
	GetInfo() string
}
type BInterface interface {
	SetInfo(string, int)
}
type People struct {
	Name string
	Age int
}
func (p People) GetInfo() string {
	return fmt.Sprintf("姓名:%v 年龄:%d", p.Name, p.Age)
}
func (p *People) SetInfo(name string, age int) {
	p.Name = name
	p.Age = age
}
func main() {
	var people = &People{
		Name: "张三",
		Age: 20,
	}
	// people 实现了 AInterface 和 BInterface
	var p1 AInterface = people
	var p2 BInterface = people
	fmt.Println(p1.GetInfo())
	p2.SetInfo("李四", 30)         // 姓名:张三 年龄:20
	fmt.Println(p1.GetInfo())      // 姓名:李四 年龄:30
}

接口嵌套

接口与接口间可以通过嵌套创造出新的接口。

type SayInterface interface {
	say()
}
type MoveInterface interface {
	move()
}
// 接口嵌套
type Animal interface {
	SayInterface
	MoveInterface
}
type Cat struct {
	name string
}
func (c Cat) say() {
	fmt.Println("喵喵喵")
}
func (c Cat) move() {
	fmt.Println("猫会动")
}
func main() {
	var x Animal
	x = Cat{name: "花花"}
	x.move()    // 猫会动
	x.say()     // 喵喵喵
}