青春纸盒子

文: 芦苇

你喜欢我笑的样子

我靠上了落寞的窗子

晚风吹起了我的袖子

明月沾湿了你的眸子


转身,你走出了两个人的圈子

树影婆娑,整座院子


挽起袖子

回头,把揽你忧伤一地的影子

装进,青春,这纸盒子


更多代码请关注我的微信小程序: "ecoder"

luwei0915

导航

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)
    }
}

 

posted on 2021-11-03 12:20  芦苇の  阅读(37)  评论(0编辑  收藏  举报