快速入门
type Usb interface {
// 生成了两个没有实现的方法
Start()
Stop()
}
type Phone struct {
}
func (p Phone) Start{
fmt.Println("手机开始工作")
}
func (p Phone) Stop{
fmt.Println("手机停止工作")
}
type Camera struct {
}
func (p Camera) Start{
fmt.Println("相机开始工作")
}
func (p Camera) Stop{
fmt.Println("相机停止工作")
}
type Coumputer struct {
}
// 只要是实现了Usb接口中声明的所有方法,就可以当做变量传到这个方法中
func (c Coumputer) Working(usb Usb){
usb.Start()
usb.Stop()
}
func main(){
cou := Coumputer
phone := Phone
camera := Camera
cou.Working(phone)
}
基本介绍
interface 类型可以定义一组方法,但是这些都不需要实现,并且interface不能包含任何变量,到某个自定义类型(比如结构体Phone)要使用的时候,再根据传入的参数不同,执行不同方法的interface定义好的方法
- 接口中的所有方法都没有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的多态和高内聚低耦合的思想
- Golang中的接口,不需要显式的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口,因此,Golang中没有implement这样的关键字
基本语法
type 接口名 interface {
method1(形参列表)(返回值列表)
method2(形参列表)(返回值列表)
}
应用场景
- 想制造轰炸机/武装直升机,专家只需要把飞机需要的功能/规格定下来,然后让别人具体实现即可
- 一个项目经理,管理三个程序员,共同开发一个软件,为了控制和管理软件,项目经理可以定义一些接口,然后由程序员具体实现
注意事项和细节
-
接口本身是不能创建实例的,但是可以指向一个实现了该接口的自定义类型的变量(实例)
-
接口中所有的方法都没有方法体,即都是没有实现的方法
-
在Golang中,一个自定义类型需要将某个接口的所有方法都实现,称之为自定义类型实现了该接口,如果只实现了一个方法是不可以的,会报错
-
只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
-
一个自定义类型可以实现多个接口
-
Golang接口中不能有任何变量
-
一个接口(比如A接口) 可以继承多个别的接口(比如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法全部实现
-
interface类型默认是一个指针(引用类型),如果没有对interface初始化就是用,那么会输出nil
9.空接口interface()没有任何方法,所以所有类型都实现了空接口,即可以把任何变量赋值给空接口类型
接口的最佳实践
实现对Hero结构体切片的排序:sort.Sort(data interface)
用系统函数,对slice切片进行排序
sort.Sort(data interface)
源码(需要实现接口定义的三个方法才可以使用这个方法,进行sort)
type Hero struct{
Name string
Age int
}
// 声明一个Hero结构体切片类型
type HeroSlice []Hero
// 实现Interface 接口的三个方法
func (hero HeroSlice) Len() int {
return len(HeroSlice)
}
// Less 决定使用什么标准进行排序,比如按照Hero的年龄从小到大排序
func (hero HeroSlice) Less(i,j int) bool {
return hero[i].Age > hero[j].Age // 根据Age 进行排序
return hero[i].Name > hero[j].Name // 根据Name 进行排序
}
//Swap 负责交换两个变量的值
func (hero HeroSlice) Swap(i,j int) {
temp := hero[i]
hero[i] = hero[j]
hero[j] = temp
// 一行代码交换两个变量的值
hero[i],hero[j] = hero[j],hero[i]
}
func main(){
// 对数组切片进行排序
var intslice = []int{0,-1,10,7,90}
sort.Ints(intslice)
// 对结构体切片进行排序
var heroes HeroSlice
for i := 0;i < 10 ;i++{
hero := Hero{
Name : fmt.Sprintf("英雄-%d",rand.Intn(100),),
Age : rand.Intn(100),
}
// 将hero append 到heroes切片
heroes = append(heroes,hero)
}
// 调用sort.Sort
sort.Sort(heroes)
}
实现接口 VS 继承
- 当A结构体继承了B结构体,那么 A 结构体 就集成了B结构体的字段和方法,并且可以直接使用
- 当A结构体需要扩展功能,同时不希望破坏继承关系,则可以通过实现某个接口实现
- 接口和继承解决的问题不同
继承的价值主要在于,解决代码的复用性和可维护性
接口的价值主要在于,设计好各种难规范(方法),让其他自定义类型取实现方法 - 接口比继承更灵活,集成式满足is a 的关系,接口只需满足like a 的关系即可
- 接口在一定程度上实现了代码解耦