golang浅析之interface(接口)

  • 发布时间:2017-01-11 13:59:22
  • 作者:伏草惟存
  • 标签:go,接口编程

golang接口简介

go语言不是传统的面向对象语言,因此没有类和继承的概念。

go语言中的接口跟java中的接口有点类似,接口可以有多个实现。

go语言的接口是go的一种类型,用来指定一组方法(方法集),go的接口归根结底就是一个方法集合。

go语言实现接口的方式不像java一样用implements关键字来实现,而是只要实现了接口中的所有方法就认为是实现了接口,这是一种规范或者叫约定(隐式实现)。

go语言中的接口往往都很短,不会存在太多方法,一般只有0到5个。


golang接口声明(定义)

type 接口名 interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
    ...
}


golang接口使用

在Java中我们通过implements可以实现接口,那么在golang中怎么实现接口呢。

在go语言中并没有关键字来标识xx类型实现了xx接口,只是存在一个约定,当xx类型实现了接口中的所有方法,那么就说明该类型实现了xx接口。

注:即使接口在类型之后才定义,二者处于不同的包中,被单独编译:只要类型实现了接口中的方法,它就实现了此接口。


golang接口实战

定义一个接口

type IHttpProxy interface {
    GET()
    POST()
}


实现一个接口

type HttpProxy struct {}

func (httpProxy *HttpProxy) GET(){

}

func (httpProxy *HttpProxy) POST(){

}


接口调用

var httpProxy IHttpProxy
httpProxy = new(HttpProxy)
httpProxy.GET()
httpProxy.POST()


golang接口命名规范

一般情况下,如果接口只包含一个方法,那么接口一般都以er结尾。比如:Logger, Reader, Printer等等。

此外如果某个接口使用的单词本身以er结尾那么一般以able结尾,比如:Recorverable。

我们也可以像java中定义接口一样使用I打头。


面向接口编程

在go中我们也可以像下面这种方式编程,方法接受参数是一个接口,我们可以传递任何一个实现了该接口的对象。

func invokeHttpGET(httpProxy IHttpProxy) {
    httpProxy.GET()
}

func invokeHttpPOST(httpProxy IHttpProxy) {
    httpProxy.POST()
}


golang接口嵌套

接口嵌套有点类似结构嵌套,就是在接口中直接引用接口。

例如下面的接口File包含了ReadWrite接口和Lock接口。

type ReadWrite interface {
    Read(b Buffer) bool
    Write(b Buffer) bool
}

type Lock interface {
    Lock()
    Unlock()
}

type File interface {
    ReadWrite
    Lock
    Close()
}


golang类型判断

这里对接口的判断有点类似多态的意思。我们可以动态的判断当前接口类型的变量指向的到底是哪个实现。在Java中我们会有下面这种代码

Person p = new Man();
Person p2 = new Woman();
xxxMethod(Person person); //这个方法既可以接受Man也可以接受Woman。我们要在xxxMethod中判断到底是Man还是Woman,然后分别做出相应的处理。

那么在Go中我们怎么来实现这种判断呢? 通过表达式:v, ok := varI.(T);来表示,varI必须是一个接口变量,如果当前接口指向的是T类型,那么返回true否则返回false。如果是true,那么v就是完整的T类型。

举个例子吧

var phone Phone
phone = new(NokiaPhone)
phone.call()
if t, ok := phone.(*NokiaPhone); ok {
    fmt.Printf("The type of areaIntf is: %T\n", t)
}

phone = new(SumsangPhone)
phone.call()
if t, ok := phone.(*SumsangPhone); ok {
    fmt.Printf("The type of areaIntf is: %T\n", t)
}

输出结果

I am Nokia, I can call you!
The type of areaIntf is: *interfaces.NokiaPhone
Sumsang call.
The type of areaIntf is: *interfaces.SumsangPhone