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