Golang

Golang接口

11-25 09:01

一、前言

熟读并理解此篇文章,基本可以在语法层面全面熟悉Golang的接口用法


二、什么时Golang接口

在Go语言中,接口(Interface)是一种类型,它规定了对象的行为。Golang接口是一种特殊的类型,它定义了一个对象应该拥有哪些方法。如果一个对象拥有接口要求的所有方法,那么这个对象就实现了该接口。


interface类型可以定义一组方法,但是这些方法不需要实现。并且interface不能包含任何变量,到某个自定义类型要使用的时候,再根据具体情况把这些方法写出来(实现方法)


Golang的接口非常灵活,耦合性很小,对Golang来说,它不关心要实现哪个接口,而是关心实现了哪个方法


三、接口基本语法

1. 声明接口:

type 接口名 interface {

method1(参数列表) 返回值列表

method2(参数列表) 返回值列表

}

2. 实现接口:

type 自定义类型 struct{}

func (n 自定义类型) method1(参数列表) 返回值列表 {

//方法实现

}

func (n 自定义类型) method2(参数列表) 返回值列表 {

//方法实现

}

3、使用接口:

func main() {

var m 自定义类型

var i 接口名 = m

m.method1(参数列表)

m.method1(参数列表)

}


四、接口快速入门 - 体验案例

package main

import "fmt"

//定义(声明)一个 Usb 接口,抽象出通过Usb接口可以做的事情
type Usb interface {

//声明两个没有实现的方法(接口中不能有方法体)

Start()

Stop()

}


//定义 Phone 类型,让 Phone 实现 Usb 接口的方法

type Phone struct { }

func (phone Phone) Start() {  //让 Phone 实现 Usb 接口的 Start() 方法

fmt.Println("手机开始工作...")

}

func (phone Phone) Stop() { //让 Phone 实现 Usb 接口的 Stop() 方法

fmt.Println("手机停止工作...")

}


//定义 Camera 类型,让 Camera 实现 Usb 接口的方法

type Camera struct {}

func (camera Camera) Start() {

fmt.Println("相机开始工作...")

}

func (camera Camera) Stop() {

fmt.Println("相机停止工作...")

}

//方法可以比接口中定义的多,但是不能少(接口中定义的方法,struct中必须全部实现,否则报错)

func (camera Camera) Print() {

fmt.Println("打印相片")

}


//编写一个 Working 方法,接收一个 Usb 接口类型的变量

type Computer struct { }

//实现 Usb 接口就是指实现了 Usb 接口声明的所有方法

func (computer Computer) Working(usb Usb) {

//通过 usb (接口类型)变量调用 start() 和 stop() 方法

usb.Start()

usb.Stop()

}


func main() {

//创建结构体变量

var phone Phone{}

camera := Camera

computer := new(Computer)

//Working方法中的usb变量,会根据传入的实参,调用对应类型中的方法

computer.Working(phone)

computer.Working(camera)

}

通过上面的快速入门案例,总结两点

1、Golang接口中所有的方法都没有方法体,即:接口的方法都是没有实现的方法。接口体现了程序设计时多态高内聚低耦合的思想

2、Golang中的接口,不需要显式的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口。因此,Golang中没有 extends 或 implement 等关键字


五、接口使用细节和注意事项

1、接口变量,可以指向一个实现了该接口的自定义类型的变量(实例)


2、接口本身不能创建实例


3、Golang接口中不能有任何变量


4、接口中的所有方法都没有方法体,即都是没有实现的方法(加入方法体会报错)


5、接口不能调用结构体中的字段,但可以通过声明的方法,操作字段

通过自定义方法操作字段 


6、接口 interface 类型默认是一个指针(引用类型),它可看做自定义类型,如果没有对 interface 初始化就使用,那么使用此类型的变量默认值是nil


7、一个自定义类型需要将某个接口的所有方法都实现,这时可以说这个自定义类型实现了该接口

假设一个接口有三个方法,一个自定义类型只有这个接口的两个方法,那也不能说实现了这个接口(必须每个都实现,缺一不可)


8、自定义类型实现某个接口时,除实现接口声明的方法外,自定义类型内部还可以有其它方法和字段,可以正常操作这些额外的字段或方法,接口变量也能正常指向这个自定义类型变量


9、一个自定义类型的只有实现了某个接口,才能将该自定义类型的变量赋值给该接口类型,自定义类型若没有实现接口就赋值(缺少接口中声明的某些方法),会报错


10、只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型

对上面代码的说明:integer 对应的类型是 Integer,Integer 又实现了 Say() 和 Print() 方法,等于 Integer 间接实现了 Interface 接口


11、一个自定义类型可以实现多个接口(有接口A声明的所有方法,也有接口B声明的所有方法,那就相当于把接口A和B都实现了)

注意:同时实现多个接口时,只能调用本接口声明的方法,不能随意穿插调用


12、接口之间也可以有继承关系,官方描述中没有“接口继承”的概念,但可以通俗理解为继承,实际操作就是 “接口嵌入”(将一个接口作为另一个接口的字段,实现接口能力的组合)

一个接口可以继承(嵌入)多个其它接口,除继承外还可以有自己的方法,这时如果要实现这个接口,必须将这个接口以及所继承接口中的方法全部都实现,若缺少未实现的方法,运行时会报错

将继承接口中的方法都实现,才算完全实现了接口

通过以上可以发现,自定义类型实现了有继承的接口,等于同时把被继承的接口也实现了,

比如上面的代码,OInterface 接口继承了 MInterface 和 NInterface 两个接口,自定义类型 O 实现了 OInterface 接口,所以 O 也同时实现了 MInterface 和 NInterface 两个接口


13、当嵌入的多个接口存在方法名相同但签名不同的情况时,会触发编译错误;若方法名和签名完全一致,则属于 “方法合并”,不会冲突

可以同时没有参数,也不会冲突

嵌入的多个接口存在方法名相同但签名不同的情况时,会触发编译错误


14、当接口定义的被自定义类型实现,且自定义类型方法的receiver为指针时,注意以下

1、使用时需对自定义类型变量携带取地址符

2、虽然是接口类型调用的方法,但依然可以修改自定义类型变量初始化时的字段的值


15、空接口 interface{} 没有任何方法,所以所有类型都实现了空接口,即:可以把任何一个变量赋给空接口

案例一:

案例二:

注意:空接口变量被赋值自定义类型后,不能调用自定义类型的字段和方法,否则报错


16、数组接口的使用方法(结合上面快速入门案例的 Usb 接口,以及实现 Usb 接口的 Phone 和 Camera 结构体)


六、接口 vs 继承(结构体组合)

实际开发中,接口和继承经常结合使用 —— 用继承实现复用代码,用接口实现多态

继承的价值主要在于:解决代码的复用性和可维护性

接口的价值主要在于:设计好各种规范(方法),让其它自定义类型去实现这些方法

接口比继承更加灵活,继承是满足“is-a”(狗是动物)的关系,接口需满足“like-a”的关系


七、接口经典案例


未完..


微信小程序
大潇博客 版权所有 Copyright ©2016~2026
京ICP备17004217号-6  合作QQ:284710375
天玺科技