30_Go基础(接口)

  1 package main
  2 
  3 import (
  4     "errors"
  5     "fmt"
  6     "reflect"
  7     "strconv"
  8 )
  9 
 10 // 1. 结构存在的意义
 11 type Cat struct{}
 12 
 13 func (c Cat) say() { fmt.Println("喵喵喵") }
 14 
 15 type Dog struct{}
 16 
 17 func (d Dog) say() { fmt.Println("汪汪汪") }
 18 
 19 func f1() {
 20     c1 := Cat{}
 21     c1.say()
 22     d1 := Dog{}
 23     d1.say()
 24     // 如果有更多的动物,就会有很多重复的代码 ...
 25 }
 26 
 27 // 2. 使用接口
 28 // 一个类型可以实现多个接口 Dog => Sayer() 和 Mover()
 29 // 一个接口,也可以实现多个类型,如 Dog, Cat 的 say()
 30 type Sayer interface {
 31     say()
 32 }
 33 
 34 func f2() {
 35     var x Sayer // 声明一个Sayer类型的变量x
 36     c := Cat{}  // 实例化一个cat
 37     d := Dog{}  // 实例化一个dog
 38     x = c       // 可以把cat实例直接赋值给x
 39     x.say()
 40     x = d
 41     d.say()
 42 }
 43 
 44 // 3. 值接收者 和 指针接收者 实现接口的区别
 45 type Mover interface {
 46     move()
 47 }
 48 
 49 func (d *Dog) move() {
 50     fmt.Println("狗会跑")
 51 }
 52 
 53 func f3() {
 54     var x Mover
 55 
 56     // 指针接收者是可以的
 57     var jww = &Dog{}
 58     x = jww
 59     x.move()
 60 
 61     // 会报错 move method has pointer receiver
 62     // var hsq = Dog{}
 63     // x = hsq
 64     // x.move()
 65 }
 66 
 67 // 4. 一个接口的方法,不一定需要由一个类型完全实现,可以嵌入其他结构体
 68 type WashingMaching interface {
 69     wash()
 70     dry()
 71 }
 72 
 73 type Dryer struct{}
 74 
 75 func (d Dryer) dry() {
 76     fmt.Println("甩一甩")
 77 }
 78 
 79 type Haier struct {
 80     Dryer // 嵌入结构体,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现
 81 }
 82 
 83 func (c Haier) wash() {
 84     fmt.Println("洗一洗") // 同时有自己的方法
 85 }
 86 
 87 func f4() {
 88     var x WashingMaching
 89 
 90     var h = Haier{}
 91     x = h // 必须一个类型实现了接口的所有方法才可以
 92     x.dry()
 93     x.wash()
 94 
 95     // d 只有 dry 方法,不能赋值给 x  "missing wash method"
 96     // d := Dryer{}
 97     // x = d
 98     // x.dry()
 99 }
100 
101 // 5. 接口嵌套
102 type Animal interface {
103     Sayer
104     Mover
105 }
106 
107 func (c *Cat) move() { // 补上猫的 move 方法
108     fmt.Println("猫会跑")
109 }
110 
111 func f5() {
112     var x Animal
113     bsm := &Cat{}
114     x = bsm
115     x.move()
116     x.say()
117 
118 }
119 
120 // 6. 空接口及应用  动态类型 动态值
121 
122 // 空接口作为函数参数
123 func show(a interface{}) {
124     fmt.Printf("type:%T value:%v\n", a, a)
125 }
126 
127 func f6() {
128     // 定义一个空接口x
129     var x interface{}
130 
131     // 空接口类型的变量可以存储任意类型的变量
132     s := "Hello 沙河"
133     x = s
134     fmt.Printf("type:%T value:%v\n", x, x) // type:string value:Hello 沙河
135     i := 100
136     x = i
137     fmt.Printf("type:%T value:%v\n", x, x) // type:int value:100
138     b := true
139     x = b
140     fmt.Printf("type:%T value:%v\n", x, x) // type:bool value:true
141 
142     // 使用空接口实现可以接收任意类型的函数参数
143     show(123)          // type:int value:123
144     show("helloworld") // type:string value:helloworld
145 }
146 
147 // 7. 接口类型判断 接口类型断言
148 func interfaceType(x interface{}) {
149     switch v := x.(type) {
150     case string:
151         fmt.Printf("x is a string,value is %v\n", v)
152     case int:
153         fmt.Printf("x is a int is %v\n", v)
154     case bool:
155         fmt.Printf("x is a bool is %v\n", v)
156     default:
157         fmt.Println("unsupport type!")
158     }
159 }
160 
161 func f7() {
162     var x interface{}
163     x = "cat"
164 
165     v, ok := x.(string)
166     if ok {
167         fmt.Println(v, ok) // cat true
168     }
169 
170     interfaceType(x) // x is a string,value is cat
171 }
172 
173 // 额外,根据函数名执行函数
174 func Call(m map[string]interface{}, name string, params ...interface{}) (result []reflect.Value, err error) {
175     f := reflect.ValueOf(m[name])
176     if len(params) != f.Type().NumIn() {
177         err = errors.New("The number of params is not adapted.")
178         return
179     }
180     in := make([]reflect.Value, len(params))
181     for k, param := range params {
182         in[k] = reflect.ValueOf(param)
183     }
184     result = f.Call(in)
185     return
186 }
187 
188 func main() {
189     funcs := map[string]interface{}{
190         "f1": f1,
191         "f2": f2,
192         "f3": f3,
193         "f4": f4,
194         "f5": f5,
195         "f6": f6,
196         "f7": f7,
197     }
198 
199     for i := 7; i < 8; i++ {
200         fName := "f" + strconv.Itoa(i)
201         Call(funcs, fName)
202     }
203 }

 

上一篇:华为VRRP-基于交换机的VRRP配置


下一篇:Java学习笔记(六)