• 30_Go基础(接口)


    package main
    
    import (
        "errors"
        "fmt"
        "reflect"
        "strconv"
    )
    
    // 1. 接口存在的意义
    type Cat struct{}
    
    func (c Cat) say() { fmt.Println("喵喵喵") }
    
    type Dog struct{}
    
    func (d Dog) say() { fmt.Println("汪汪汪") }
    
    func f1() {
        c1 := Cat{}
        c1.say()
        d1 := Dog{}
        d1.say()
        // 如果有更多的动物,就会有很多重复的代码 ...
    }
    
    // 2. 使用接口
    // 一个类型可以实现多个接口 Dog => Sayer() 和 Mover()
    // 一个接口,也可以实现多个类型,如 Dog, Cat 的 say()
    type Sayer interface {
        say()
    }
    
    func f2() {
        var x Sayer // 声明一个Sayer类型的变量x
        c := Cat{}  // 实例化一个cat
        d := Dog{}  // 实例化一个dog
        x = c       // 可以把cat实例直接赋值给x
        x.say()
        x = d
        d.say()
    }
    
    // 3. 值接收者 和 指针接收者 实现接口的区别
    type Mover interface {
        move()
    }
    
    func (d *Dog) move() {
        fmt.Println("狗会跑")
    }
    
    func f3() {
        var x Mover
    
        // 指针接收者是可以的
        var jww = &Dog{}
        x = jww
        x.move()
    
        // 会报错 move method has pointer receiver
        // var hsq = Dog{}
        // x = hsq
        // x.move()
    }
    
    // 4. 一个接口的方法,不一定需要由一个类型完全实现,可以嵌入其他结构体
    type WashingMaching interface {
        wash()
        dry()
    }
    
    type Dryer struct{}
    
    func (d Dryer) dry() {
        fmt.Println("甩一甩")
    }
    
    type Haier struct {
        Dryer // 嵌入结构体,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现
    }
    
    func (c Haier) wash() {
        fmt.Println("洗一洗") // 同时有自己的方法
    }
    
    func f4() {
        var x WashingMaching
    
        var h = Haier{}
        x = h // 必须一个类型实现了接口的所有方法才可以
        x.dry()
        x.wash()
    
        // d 只有 dry 方法,不能赋值给 x  "missing wash method"
        // d := Dryer{}
        // x = d
        // x.dry()
    }
    
    // 5. 接口嵌套
    type Animal interface {
        Sayer
        Mover
    }
    
    func (c *Cat) move() { // 补上猫的 move 方法
        fmt.Println("猫会跑")
    }
    
    func f5() {
        var x Animal
        bsm := &Cat{}
        x = bsm
        x.move()
        x.say()
    
    }
    
    // 6. 空接口及应用  动态类型 动态值
    
    // 空接口作为函数参数
    func show(a interface{}) {
        fmt.Printf("type:%T value:%v\n", a, a)
    }
    
    func f6() {
        // 定义一个空接口x
        var x interface{}
    
        // 空接口类型的变量可以存储任意类型的变量
        s := "Hello 沙河"
        x = s
        fmt.Printf("type:%T value:%v\n", x, x) // type:string value:Hello 沙河
        i := 100
        x = i
        fmt.Printf("type:%T value:%v\n", x, x) // type:int value:100
        b := true
        x = b
        fmt.Printf("type:%T value:%v\n", x, x) // type:bool value:true
    
        // 使用空接口实现可以接收任意类型的函数参数
        show(123)          // type:int value:123
        show("helloworld") // type:string value:helloworld
    }
    
    // 7. 接口类型判断 接口类型断言
    func interfaceType(x interface{}) {
        switch v := x.(type) {
        case string:
            fmt.Printf("x is a string,value is %v\n", v)
        case int:
            fmt.Printf("x is a int is %v\n", v)
        case bool:
            fmt.Printf("x is a bool is %v\n", v)
        default:
            fmt.Println("unsupport type!")
        }
    }
    
    func f7() {
        var x interface{}
        x = "cat"
    
        v, ok := x.(string)
        if ok {
            fmt.Println(v, ok) // cat true
        }
    
        interfaceType(x) // x is a string,value is cat
    }
    
    // 额外,根据函数名执行函数
    func Call(m map[string]interface{}, name string, params ...interface{}) (result []reflect.Value, err error) {
        f := reflect.ValueOf(m[name])
        if len(params) != f.Type().NumIn() {
            err = errors.New("The number of params is not adapted.")
            return
        }
        in := make([]reflect.Value, len(params))
        for k, param := range params {
            in[k] = reflect.ValueOf(param)
        }
        result = f.Call(in)
        return
    }
    
    func main() {
        funcs := map[string]interface{}{
            "f1": f1,
            "f2": f2,
            "f3": f3,
            "f4": f4,
            "f5": f5,
            "f6": f6,
            "f7": f7,
        }
    
        for i := 7; i < 8; i++ {
            fName := "f" + strconv.Itoa(i)
            Call(funcs, fName)
        }
    }
  • 相关阅读:
    overflow:hidden三个作用
    git提交代码步骤以及创建issue事项
    Vue3.0中setup函数的使用
    样式rpx
    js函数
    数据类型
    进制转换
    事件绑定
    微信小程序基础
    “AI+”改变世界!不同领域的5大人工智能趋势
  • 原文地址:https://www.cnblogs.com/luwei0915/p/15503027.html
Copyright © 2020-2023  润新知