美文网首页
Golang——接口

Golang——接口

作者: Cici冬雪 | 来源:发表于2020-06-13 15:27 被阅读0次

    接口(interface)定义一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。
    在go语言中,接口(interface)是一种抽象的类型
    interface是一组method 的集合,是duck-type programming的一种体现,不关心属性(数据),只关心行为(方法)
    Go语言提倡面向接口编程
    定义接口如下:

    type 接口类型名 interface {
        方法名1(参数列表1) 返回值列表1
        方法名2(参数列表2) 返回值列表2
    }
    

    其中,

    • 接口名:Go语言中的接口命名时候,一般会再单次后面添加er,例如写文件的接口叫Writer
    type animal interface {
        eat() string
    }
    

    一个对象只要全部实现了接口中的方法,那么就实现了这个接口。

    package main
    
    import (
        "fmt"
    )
    
    type Cat struct {}
    
    func (c *Cat)Eat() string { return "吃鱼" }
    
    type Dog struct {}
    
    func (d *Dog)Eat() string { return "吃骨头"}
    
    type Animal interface {
        Eat() string
    }
    
    func main(){
        
        var a []Animal
    
        c := Cat{}
        d := Dog{}
    
        // fmt.Println(c.Eat())
        // fmt.Println(d.Eat())
    
        a = append(a, &c)
        a = append(a, &d)
    
        for _, value := range a {
            fmt.Println(value.Eat())
        }
    }
    

    一个类型可以实现多个接口。

    package main
    
    import (
        "fmt"
    )
    
    type Eater interface {
        Eat() string
    }
    
    type Mover interface {
        Move() string
    }
    
    type Cat struct { name string}
    
    func (c *Cat)Eat() string { return c.name + "吃鱼" }
    
    func (c *Cat)Move() string { return c.name + "猫走" }
    
    func main(){
        c := Cat{name: "Tom"}
        fmt.Println(c.Eat())
        fmt.Println(c.Move())
    }
    
    

    多个类型实现同一个接口。
    并且一个接口的方法,不一定由一个类型全部实现,接口的方法可以通过类型中嵌入其它类型或者结构体实现。

    package main
    
    import (
        "fmt"
    )
    
    type Tester interface {
        Eat() string
        Move() string
    }
    
    type Animal struct {
        name string
    }
    type Cat struct { 
        age int
        a Animal
    }
    
    func (c *Cat)Eat() string { return "吃鱼" }
    
    func (a *Animal)Move() string { return "猫走" }
    
    func main(){
        c := Cat{
            age: 6,
            a: Animal{
                name: "Tom",
            },
        }
        fmt.Println(c.Eat())
        fmt.Println(c.a.Move())
    }
    

    接口嵌套

    package main
    
    import (
        "fmt"
    )
    
    type Eater interface {
        Eat() string
    }
    
    type Mover interface {
        Move() string
    }
    
    type Animal interface {
        Eater
        Mover
    }
    
    type Cat struct {}
    
    func (c *Cat)Eat() string { return "吃鱼" }
    
    func (c *Cat)Move() string { return "猫走" }
    
    type Dog struct {}
    
    func (d *Dog)Eat() string { return "吃骨头"}
    
    func (d *Dog)Move() string { return "狗走" }
    
    
    func main(){
        
        var a []Animal
    
        c := Cat{}
        d := Dog{}
    
        a = append(a, &c)
        a = append(a, &d)
    
        for _, value := range a {
            fmt.Println(value.Eat())
            fmt.Println(value.Move())
        }
    }
    

    空接口
    没有定义任何方法的接口,因此任何类型都实现了空接口。
    空接口类型的变量可以存储任意类型的变量。
    主要作用是:

    • 空接口作为参数或者返回值,可接受任何类型
    • 使用空接口可以实现任意值的字典
    package main
    
    import (
        "fmt"
    )
    
    //空接口作为参数,可接受任何类型
    func showType(a interface{}){
        fmt.Printf("%T\n", a)
    }
    
    func main(){
        
        //空接口可用这种方式定义
        var x interface{}
    
        x = 100
        fmt.Println(x)
        showType(x)
    
        x = "哈哈"
        fmt.Println(x)
        showType(x)
    
        x = false
        fmt.Println(x)
        showType(x)
    
        x = struct{ name string}{ name: "张三" }
        fmt.Println(x)
        showType(x)
    
        //使用空接口可以实现任意值的字典
        m := make(map[string]interface{}, 10)
        m["a"] = 1
        m["b"] = "b"
        m["c"] = true
        m["d"] = 12.23
        fmt.Println(m)
    }
    输出结果是
    100
    int
    哈哈
    string
    false
    bool
    {张三}
    struct { name string }
    map[a:1 b:b c:true d:12.23]
    

    类型断言
    空接口可以存储任意类型的值,则如何获取其存储的具体数据呢?
    采用格式是x.(T),返回值是两个:第二是bool类型,true断言成功,false断言失败;第一值是,如果断言正确返回值,否则返回断言类型的默认值。

    • x:类型为interface{}的变量
    • T:表示断言x可能是的类型
    package main
    
    import (
        "fmt"
    )
    
    func main(){
        
        //空接口
        var x interface{}
    
        x = 100
        //类型断言
        v1, ok := x.(int)
        fmt.Println(ok)
        fmt.Println(v1)
    
        v2, ok := x.(bool)
        fmt.Println(ok)
        fmt.Println(v2)
    
        x = "哈哈"
        //类型断言
        v3, ok := x.(string)
        fmt.Println(ok)
        fmt.Println(v3)
    
        v4, ok := x.(int)
        fmt.Println(ok)
        fmt.Println(v4)
    }
    输出结果是:
    true
    100
    false
    false
    true
    哈哈
    false
    0
    

    值接收者和指针接收者区别
    值接收者的话,值接收者和指针接收者都可以用
    指针接收者的话,只能指针接收者可以用

    package main
    
    import (
        "fmt"
    )
    
    type Mover interface {
        Move() string
    }
    
    type Cat struct {
        name string
    }
    
    //值接收者
    func (c Cat)Move() string { return c.name + "吃鱼" }
    
    //指针接收者
    // func (c *Cat)Move() string { return c.name + "吃鱼" }
    
    func main(){
        //方法采用值接收者时候,值和指针传参都可以
        var m Mover
        c := Cat{name: "Tom"}
        m = c
        fmt.Println(m)
        fmt.Println(m.Move())
    
        s := &Cat{name: "Jerry"}
        m = s
        fmt.Println(m)
        fmt.Println(m.Move())
    
        //方法采用指针接收者时候,只能是指针传参
        // var m Mover
        // c := &Cat{name: "Tom"}
        // m = c
        // fmt.Println(m)
        // fmt.Println(m.Move())
    }
    

    相关文章

      网友评论

          本文标题:Golang——接口

          本文链接:https://www.haomeiwen.com/subject/uumetktx.html