golang interface理解

来源:互联网 发布:淘宝网上的女装 编辑:程序博客网 时间:2024/05/16 11:08

最早对interface的认知比较片面,很多人都说interface与channel是go语言的灵魂。然而在工作中使用的机会比较少,发现自己对interface的理解太片面。下面就记录并总结下go中的interface。

interface是个啥

go程序设计中是这样解释的“接口是一种抽象类型,他并没有暴露所包含数据的布局或者内部结构,当然也没有那些数据的基本操作,它所提供的仅仅是一些方法而已”。根据上面的说明我们可以提炼出接口是对一些方法的封装
很多的C++程序员吐槽go不便之处就是没有’泛型’我们没法使用模板啊,go语言中确实没有,但是go提供了interface让我们可以实现这种泛型。正如上面所说interface是一种抽象类型,是一组方法的集合,我们可以把它看成一种定义内部方法的动态数据类型,任意实现了这些方法的数据类型都可以认为是特定的数据类型。(是不是有点像是C++中模板类)。
正如sort包中

package sort// A type, typically a collection, that satisfies sort.Interface can be// sorted by the routines in this package. The methods require that the// elements of the collection be enumerated by an integer index.type Interface interface {    // Len is the number of elements in the collection.    Len() int    // Less reports whether the element with    // index i should sort before the element with index j.    Less(i, j int) bool    // Swap swaps the elements with indexes i and j.    Swap(i, j int)}

在sort包中提供了三个方法,只要我们实现了这三个方法我们就可以对任何的类型进行排序。
看过了官方的sort是如何写的我们也自己动手写一个例子

package mainimport "fmt"type classmate struct {    class uint32    grade uint32    age   uint32    name  string}type info interface {    Len() int    Compare(agex,agei uint32)uint32}type listInfo []classmatetype listuint []uint32func (this listInfo)Len()(int){    return len(this)}func (this listInfo)Compare(i,j uint32)(uint32){    if this[i].grade > this[j].grade{        return this[i].grade    }    return this[j].grade}func (this listuint)Len()(int){    return len(this)}func (this listuint)Compare(i,j uint32)(uint32){    if this[i] > this[j]{        return this[i]    }    return this[j]}func main(){    lInfo := listInfo{        classmate{1,1,6,"tom"},        classmate{2,3,8,"jim"},    }    fmt.Println("len is ", lInfo.Len())    garde := lInfo.Compare(0,1)    fmt.Printf("grade is %d \n",garde)    uInfo := listuint{9,6,8}    fmt.Println("len is ", uInfo.Len())    fmt.Printf("compare is %d ",uInfo.Compare(1,2))}

示例中我们的interface中包含了两个方法,len与compare,获取长度与比较大小,我们分别为不同的类型实现了接口中的方法,是不是有点像C++中的函数重载(C++中函数重载要求参数个数或者参数类型不同)。同时我们也发现我们为不同的类型实现了方法,所以说一个接口类型不会去关心到底是什么数据类型实现了他自身。接口类型的本质就是如果一个数据类型实现了自身的方法集,那么该接口类型变量就能够引用该数据类型的值。
在上面我们提到了sort包,我们只要实现了其提供的三个方法就可以对任何类型进行排序,因为我们实现了它的接口类型。

package mainimport "fmt"type classmate struct {    class uint32    grade uint32    age   uint32    name  string}type classinfo struct {    total uint32    grade uint32}type info interface {    coutInfo()    changeInfo(grade uint32)}func (this *classmate)coutInfo(){    fmt.Println("info is ",this)}func (this *classmate)changeInfo(grade uint32){    this.grade = grade    fmt.Println("info is ",this)}func (this *classinfo)coutInfo(){    fmt.Println("info is ",this)}func (this *classinfo)changeInfo(grade uint32){    this.grade = grade    fmt.Println("info is ",this)}func interTest(test info,grade uint32){    test.coutInfo()    test.changeInfo(grade)}func main(){    mate := &classmate{        class: 1,        grade:1,        age:6,        name:"jim",    }    info := &classinfo{        total:30,        grade:5,    }    interTest(mate,3)    interTest(info,8)}

输出:

info is  &{1 1 6 jim}info is  &{1 3 6 jim}info is  &{30 5}info is  &{30 8}

相信这个例子可以帮助我们更好的理解函数interTest的第一个输入参数并没有要求参数的具体类型,而是一个接口类型。

使用interface的注意事项

  1. 将对象赋值给接口变量时会复制该对象。
  2. 接口使用的是一个名为itab的结构体存储的
    type iface struct{
    tab *itab // 类型信息
    data unsafe.Pointer // 实际对象指针
    }
  3. 只有接口变量内部的两个指针都为nil的时候,接口才等于nil。
原创粉丝点击