一、interface简介
在golang中,interface本身也是一种类型,它代表的是一个方法的集合。任何类型只要实现了接口中声明的所有方法,那么该类就实现了该接口。与其他语言不同, golang 并不需要显示声明类型实现了某个接口,而是由编译器和 runtime 进行检查。
如何理解go 语言中的interface ? 只需记住以下三点即可:
1. interface 是方法声明的集合
2. 任何类型的对象实现了在interface 接口中声明的全部方法,则表明该类型实现了该接口。
3. interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。
二、类型断言和类型转换区别
1.Go 语言中不允许隐式类型转换,也就是说 = 两边,不允许出现类型不相同的变量。类型转换、类型断言本质都是把一个类型转换成另外一个类型。不同之处在于,类型断言是对接口变量进行的操作。
类型转换的语法为:<结果类型> := <目标类型> ( <表达式> )
2.传入参数接口的时候,如果我们希望确切知道它具体类型,那么就要用到类型判断了。有两种类型判断方法:
1).变量.(类型) //判断是不是某个具体类型
var i interface{}=new(Person)
p,ok := i.(Peron) //安全类型断言,如果不加ok是非安全的,断言失败也不会panic
if ok{
}
2).switch 变量.(type) //返回具体类型,必须搭配swith语句
三、如何利用interface实现多态?
type Car interface {
NameGet() string
Run(n int)
Stop()
}
type BMW struct {
Name string
}
func (this *BMW) NameGet() string {
return this.Name
}
func (this *BMW) Run(n int) {
fmt. Printf (“BMW is running of num is %d \n”, n)
}
func (this *BMW) Stop() {
fmt.Printf(“BMW is stop \n”)
}
type Benz struct {
Name string
}
func (this *Benz) NameGet() string {
return this.Name
}
func (this *Benz) Run(n int) {
fmt.Printf(“Benz is running of num is %d \n”, n)
}
func (this *Benz) Stop() {
fmt.Printf(“Benz is stop \n”)
}
func (this *Benz) ChatUp() {
fmt.Printf(“ChatUp \n”)
}
func main() {
var car Car
fmt.Println(car) // <nil>
var bmw BMW = BMW{Name: “宝马”}
car = &bmw
fmt.Println(car.NameGet()) //宝马
car.Run(1) //BMW is running of num is 1
car.Stop() //BMW is stop
benz := &Benz{Name: “大奔”}
car = benz
fmt.Println(car.NameGet()) //大奔
car.Run(2) //Benz is running of num is 2
car.Stop() //Benz is stop
//car.ChatUp() //ERROR: car.ChatUp undefined (type Car has no field or method ChatUp)
}
四、接口嵌套
一个接口可以嵌套在另外的接口,实现该接口的话即需要实现2个接口的方法。
type Car interface {
NameGet() string
Run(n int)
Stop()
}
type Used interface {
Car
Cheap()
}
五、匿名接口
1.在golang也可以给结构体定义一个匿名interface field,比如在sort库 中,就有如下写法:
type Interface interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
type reverse struct {
Interface
}
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
func Reverse(data Interface) Interface {
return &reverse{data}
}
在reverse结构体内嵌了一个Interface的interface,并且,提供了单独的Less函数定义,却没有提供 Len, Swap 的定义。首先,根据结构体内嵌其它匿名字段的定义,可以推知,理论上,调用reverse.Len, reverse.Swap,肯定是会直接传递到 reverse.Interface.Len 和 reverse.Interface.Swap,即,和直接调用Interface的同名函数没有任何区别。
2.为何采用这种设计方式呢?
1)匿名接口的方式不依赖具体实现,可以对任意实现了该接口的类型进行重写。
2)匿名接口还有一个作用就是对 结构体添加一些约束 ,必须使用实现了该接口的类型来构造实例。