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