zoukankan      html  css  js  c++  java
  • Go之接口interface(1)

    1. 什么是interface
    在此之前,我们遇到的都是具体的类型,比如数字类型、切片类型等等。对于这些具体的类型,我们总是能知道它是什么、可以利用它来做什么,比如对于一个数字类型,我们知道可以对其进行算数操作;对于一个切片类型,我们知道可以取下标操作等等。但是,接口类型是一种抽象的类型,我们并不能知道接口内存放的对象的值是什么,也不知道这个对象支持哪些操作。唯一知道的就是可以利用接口提供的方法来做一些事情。

    简单的说,interface是一组method的组合,我们通过interface来定义对象的一组行为。我们称一个实现了这些方法的具体类型为这个接口类型的实例

    首先,来看一个简单的例子。

    下面的语句定义了一个简单的接口:
    type geometry interface {
    area() float64
    perimeter() float64
    }


    然后定义一个结构体 circle:
    type circle struct{
    radius float64
    }


    接着,对 circle 类型实现 geometry 接口。我们说一个类型实现了某个接口,就是说这个类型实现了该接口中定义的所有方法。
    func (c circle) area() float64 {
    return math.Pi * c.radius * c.radius
    }

    func (c circle) perimeter() float64 {
    return 2 * math.Pi * c.radius
    }


    我们再定义一个显示方法show(),如下:
    func show(g geometry) {
    fmt.Println(g)
    fmt.Println(g.area())
    fmt.Println(g.perimeter())
    }


    最后,在 main() 方法中初始化一个 circle 对象,并执行相应函数。
    func main() {
    c := circle{radius:3} // 初始化一个 circle 对象
    show(c)
    }


    表达一个类型属于某个接口,只要这个类型实现了这个接口。所以,下面语句是合理的:
    var g geometry
    c := circle{radius:3}
    g = c // ok,因为 circle 类型实现了 geometry 接口内声明的所有方法。因此可以说 circle 属于 geometry

    但是,假设现在有一个类型是 rect,但是它只实现了 geometry 接口中的 area() 方法,如下:
    type rect struct {
    width, height float64
    }
    func (r rect) area() float64 {
    return r.height * r.width
    }


    那么此时,执行如下语句就是错误的:
    r := rect{10, height:5}
    g = r // compile error, rect type lacks perimeter() method

    此外,一个对象还可以实现任意多个interface,例如,现在再定义一个Foo 接口(这里只是为了示例,并无意义),如下:
    type Foo interface {
    foo()
    }

    那么,circle 对象还可以实现该接口。同样的,只要 circle 类型实现了 Foo 接口内定义的所有方法,我们就说 circle 也属于 Foo
    type Foo interface {
    sayHi(s string)
    }

    func (c circle) sayHi(s string) {
    fmt.Println("Hi, I am ", s)
    }

    // 以下是成立的
    var f Foo
    f = c
    f.sayHi("circle")


    总结:一个 interface 可以被任意个不同类型的对象实现(比如,geometry 接口可以被 circle、rect 等对象实现);一个对象也可以实现任意个 interface(比如,circle 类型就实现了 geometry 和 Foo 这两个接口 )。最关键的是,我们说一个类型实现了某个接口,指的是这个类型实现了该接口中定义的所有方法。一旦一个类型实现了某个接口,我们就说这个类型属于该接口,从而可以把这个类型的值赋给其接口类型的值。

    最后,任意的类型都实现了空interface(写为:interface{}),也就是包含 0 个method 的interface。

    2. interface 值
    如果我们定义了一个 interface 的变量,那么这个变量到底可以存放什么值呢?其实这个问题的答案在第1部分的例子中已经回答了,在上面的例子中,我们定义了一个 geometry 接口的变量(var g geometry),可以把 circle 类型的变量 c 赋值给 g——因为 circle 类型实现了 geometry 接口。当然,如果还有别的类型,比如 rect、triangle...只要它们实现了 geometry 接口,那么变量 g 就都可以“接受”它们。总的来说,如果我们定义了一个 interface 的变量,那么这个变量里面就可以存实现了这个 interface 的任意类型的对象。

    3. 空 interface(interface{})
    空 interface不包含任何的 method,正因为如此,可以认为所有的类型都实现了 interface{}。空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。它有点类似于C语言的 void* 类型。一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值。
    示例代码:
    var v interface{} // v定义为空接口
    var i int = 23
    var s string = "hello, zju"
    // v 可以存储任意类型的值
    v = i // ok
    v = s // ok


    参考
    关于interface的一篇还不错的文章
    https://www.jb51.net/article/56812.htm

  • 相关阅读:
    Element-ui 复选框使用问题
    脚手架 oss 直传
    门外汉 avue使用
    cookie关闭浏览器清除
    关于(Incorrect string value: 'xF0x9Fx8ExBE' for column 'xxx' at row)报错
    扫码登录
    微信支付
    vue 腾讯地图 javaScriptAPI GL 多个markers自适应 (3)
    vue props 一次性传多个值
    vuex 的简单使用
  • 原文地址:https://www.cnblogs.com/kkbill/p/11727415.html
Copyright © 2011-2022 走看看