七叶笔记 » golang编程 » golang基础之interface

golang基础之interface

一、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)匿名接口还有一个作用就是对 结构体添加一些约束 ,必须使用实现了该接口的类型来构造实例。

相关文章