接口
1. 定义: Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
1 2 3 4 5
| 1type example interface{
2 Method1(参数列表) 返回值列表
3 Method2(参数列表) 返回值列表
4}
5 |
2.interface类型默认是一个指针
1 2 3 4 5 6 7 8 9 10
| 1type example interface{
2
3 Method1(参数列表) 返回值列表
4 Method2(参数列表) 返回值列表
5 …
6 }
7
8 var a example
9 a.Method1()
10 |
3. 接口实现
- a. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字
- b. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
- c. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| 1package main
2
3import "fmt"
4
5type Car interface {
6 GetName() string
7 Run()
8 DiDi()
9}
10
11type Test interface {
12 Hello()
13}
14
15type BMW struct {
16 Name string
17}
18
19func (p *BMW) GetName() string {
20 return p.Name
21}
22
23func (p *BMW) Run() {
24 fmt.Printf("%s is running\n", p.Name)
25}
26
27func (p *BMW) DiDi() {
28 fmt.Printf("%s is didi\n", p.Name)
29}
30func (p *BMW) Hello() {
31 fmt.Printf("%s is hello\n", p.Name)
32}
33
34type BYD struct {
35 Name string
36}
37
38func (p *BYD) GetName() string {
39 return p.Name
40}
41
42func (p *BYD) Run() {
43 fmt.Printf("%s is running\n", p.Name)
44}
45
46func (p *BYD) DiDi() {
47 fmt.Printf("%s is didi\n", p.Name)
48}
49
50func main() {
51 var car Car
52 var test Test
53 fmt.Println(car)
54
55 // var bwm = BMW{}
56 // bwm.Name = "宝马"
57 bwm := &BMW{
58 Name: "宝马",
59 }
60 car = bwm
61 car.Run()
62
63 test = bwm
64 test.Hello()
65
66 byd := &BMW{
67 Name: "比亚迪",
68 }
69 car = byd
70 car.Run()
71 // var a interface{}
72 // var b int
73 // var c float32
74
75 // a = b
76 // a = c
77 // fmt.Printf("type of a %T\n", a)
78}
79 |
接口实现案例Car
4.多态:一种事物的多种形态,都可以按照统一的接口进行操作
sort排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| 1package main
2
3import (
4 "fmt"
5 "math/rand"
6 "sort"
7)
8
9type Student struct {
10 Name string
11 Id string
12 Age int
13}
14
15type Book struct {
16 Name string
17 Author string
18}
19
20type StudentArray []Student
21
22func (self StudentArray) Len() int {
23 return len(self)
24}
25
26func (self StudentArray) Less(i, j int) bool {
27 return self[i].Name > self[j].Name
28}
29
30func (self StudentArray) Swap(i, j int) {
31 self[i], self[j] = self[j], self[i]
32}
33
34func main() {
35 var stus StudentArray
36
37 for i := 0; i < 10; i++ {
38 stu := Student{
39 Name: fmt.Sprintf("stu%d", rand.Intn(100)),
40 Id: fmt.Sprintf("110%d", rand.Int()),
41 Age: rand.Intn(100),
42 }
43 stus = append(stus, stu)
44 }
45
46 for _, v := range stus {
47 fmt.Println(v)
48 }
49
50 fmt.Println()
51
52 sort.Sort(stus)
53
54 for _, v := range stus {
55 fmt.Println(v)
56 }
57}
58 |
5. 接口嵌套:一个接口可以嵌套在另外的接口,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 1type ReadWrite interface {
2 Read(b Buffer) bool
3 Write(b Buffer) bool
4}
5type Lock interface {
6 Lock()
7 Unlock()
8}
9type File interface {
10 ReadWrite
11 Lock
12 Close()
13}
14 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 1package main
2
3import "fmt"
4
5type Reader interface {
6 Read()
7}
8
9type Writer interface {
10 Write()
11}
12
13type ReadWriter interface {
14 Reader
15 Writer
16}
17
18type File struct {
19}
20
21func (self *File) Read() {
22 fmt.Println("read data")
23}
24
25func (self *File) Write() {
26 fmt.Println("write data")
27}
28
29func Test(rw ReadWriter) {
30 rw.Read()
31 rw.Write()
32}
33
34func main() {
35 var f *File
36 var b interface{}
37 b = f
38 // Test(f)
39
40 v, ok := b.(ReadWriter)
41 fmt.Println(v, ok)
42}
43 |
接口嵌套文件读写案例
6. 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法进行转换:
1 2 3 4 5
| 1var t int
2 var x interface{}
3 x = t
4 y, ok = x.(int) //转成int,带检查
5 |
7. 练习,写一个函数判断传入参数的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| 1package main
2
3import (
4 "fmt"
5)
6
7type Studnet struct {
8 Name string
9 Sex string
10}
11
12func Test(a interface{}) {
13 // b, ok := a.(int)
14 b, ok := a.(Studnet)
15 if ok == false {
16 fmt.Println("convert failed")
17 return
18 }
19 // b += 3
20 fmt.Println(b)
21}
22
23func just(items ...interface{}) {
24 for index, v := range items {
25 switch v.(type) {
26 case bool:
27 fmt.Printf("%d params is bool, value is %v\n", index, v)
28 case int, int32, int64:
29 fmt.Printf("%d params is int, value is %v\n", index, v)
30 case float32, float64:
31 fmt.Printf("%d params is float, value is %v\n", index, v)
32 case string:
33 fmt.Printf("%d params is string, value is %v\n", index, v)
34 case Studnet:
35 fmt.Printf("%d params is student, value is %v\n", index, v)
36 case *Studnet:
37 fmt.Printf("%d params is *student, value is %v\n", index, v)
38 }
39 }
40}
41
42func main() {
43 var a interface{}
44 var b int
45 Test(b)
46 a = b
47 c := a.(int)
48 fmt.Printf("%d %T\n", a, a)
49 fmt.Printf("%d %T\n", c, c)
50
51 var d Studnet = Studnet{
52 Name: "stu1",
53 Sex: "female",
54 }
55 Test(d)
56 just(28, 8.2, "this is a test", d, &d)
57}
58 |
8. 类型断言,采用type switch方式
9. 空接口.interface{}
空接口没有任何方法,所以所有类型都实现了空接口。
1 2 3 4
| 1var a int
2 var b interface{}
3 b = a
4 |
10.判断一个变量是否实现了指定接口
1 2 3 4 5 6 7 8
| 1type Stringer interface {
2 String() string
3 }
4 var v MyStruct
5 if sv, ok := v.(Stringer); ok {
6 fmt.Printf(“v implements String(): %s\n”, sv.String());
7 }
8 |
11. 实现一个通用的链表类
link.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 1package main
2
3import (
4 "fmt"
5)
6
7type LinkNode struct {
8 data interface{}
9 next *LinkNode
10}
11
12type Link struct {
13 head *LinkNode
14 tail *LinkNode
15}
16
17func (p *Link) InsertHead(data interface{}) {
18 node := &LinkNode{
19 data: data,
20 next: nil,
21 }
22
23 if p.tail == nil && p.head == nil {
24 p.tail = node
25 p.head = node
26 return
27 }
28
29 node.next = p.head
30 p.head = node
31}
32func (p *Link) InsertTail(data interface{}) {
33 node := &LinkNode{
34 data: data,
35 next: nil,
36 }
37
38 if p.tail == nil && p.head == nil {
39 p.tail = node
40 p.head = node
41 return
42 }
43
44 p.tail.next = node
45 p.tail = node
46}
47
48func (p *Link) Trans() {
49 q := p.head
50 for q != nil {
51 fmt.Println(q.data)
52 q = q.next
53 }
54}
55 |
main.go
1 2 3 4 5 6 7 8 9 10 11
| 1package main
2
3func main() {
4 var initLink Link
5 for i := 0; i < 10; i++ {
6 // initLink.InsertHead(i)
7 initLink.InsertTail(i)
8 }
9 initLink.Trans()
10}
11 |
12. interface{},接口中一个方法也没有,所以任何类型都实现了空接口,也就是任何变量都可以赋值给空接口。
1 2 3 4
| 1var a int
2 var b interface{}
3 b = a
4 |
13. 变量slice和接口slice之间赋值操作,for range
1 2 3 4
| 1var a []int
2 var b []interface{}
3 b = a
4 |
14. 实现一个负载均衡调度算法,支持随机、轮训等算法
1 2 3 4 5 6
| 1package balance
2
3type Balancer interface {
4 DoBalance([]*Instance, ...string) (*Instance, error)
5}
6 |
balance.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 1package balance
2
3import "strconv"
4
5type Instance struct {
6 host string
7 port int
8}
9
10func NewInstance(host string, port int) *Instance {
11 return &Instance{
12 host: host,
13 port: port,
14 }
15}
16
17func (p *Instance) GetHost() string {
18 return p.host
19}
20
21func (p *Instance) GetPort() int {
22 return p.port
23}
24
25func (p *Instance) String() string {
26 return p.host + ":" + strconv.Itoa(p.port)
27}
28 |
instance.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 1package balance
2
3import "fmt"
4
5type BalanceMgr struct {
6 allBalancer map[string]Balancer
7}
8
9var mgr = BalanceMgr{
10 allBalancer: make(map[string]Balancer),
11}
12
13func (p *BalanceMgr) RegisterBalancer(name string, b Balancer) {
14 p.allBalancer[name] = b
15}
16
17func RegisterBalancer(name string, b Balancer) {
18 mgr.RegisterBalancer(name, b)
19}
20
21func DoBalance(name string, insts []*Instance) (inst *Instance, err error) {
22 balancer, ok := mgr.allBalancer[name]
23 if !ok {
24 err = fmt.Errorf("Not found %s balancer", name)
25 return
26 }
27 fmt.Printf("use %s balance\n", name)
28 inst, err = balancer.DoBalance(insts)
29 return
30}
31 |
mgr.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 1package balance
2
3import (
4 "errors"
5 "math/rand"
6)
7
8func init() {
9 RegisterBalancer("random", &RandomBalance{})
10}
11
12type RandomBalance struct {
13}
14
15func (p *RandomBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) {
16 if len(insts) == 0 {
17 err = errors.New("No instance")
18 return
19 }
20 lens := len(insts)
21 index := rand.Intn(lens)
22 inst = insts[index]
23 return
24}
25 |
random.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 1package balance
2
3import (
4 "errors"
5)
6
7func init() {
8 RegisterBalancer("roundrobin", &RoundRobinBalance{})
9}
10
11type RoundRobinBalance struct {
12 curIndex int
13}
14
15func (p *RoundRobinBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) {
16 if len(insts) == 0 {
17 err = errors.New("No instance")
18 return
19 }
20 lens := len(insts)
21 if p.curIndex >= lens {
22 p.curIndex = 0
23 }
24 inst = insts[p.curIndex]
25 p.curIndex = (p.curIndex + 1) % lens
26 return
27}
28 |
roundrobin.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| 1package main
2
3import (
4 "fmt"
5 "go_dev/day7/example/example1/balance"
6 "hash/crc32"
7 "math/rand"
8)
9
10type HashBalance struct {
11}
12
13func init() {
14 balance.RegisterBalancer("hash", &HashBalance{})
15}
16
17func (p *HashBalance) DoBalance(insts []*balance.Instance, key ...string) (inst *balance.Instance, err error) {
18 var defkey string = fmt.Sprintf("%d", rand.Int())
19 if len(key) > 0 {
20 // err := fmt.Errorf("hash balance must pass the hash key")
21 defkey = key[0]
22 }
23 lens := len(insts)
24 if lens == 0 {
25 err = fmt.Errorf("No backend instance")
26 return
27 }
28 crcTable := crc32.MakeTable(crc32.IEEE)
29 hashVal := crc32.Checksum([]byte(defkey), crcTable)
30 index := int(hashVal) % lens
31 inst = insts[index]
32
33 return
34}
35 |
hash.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| 1package main
2
3import (
4 "fmt"
5 "go_dev/day7/example/example1/balance"
6 "math/rand"
7 "os"
8 "time"
9)
10
11func main() {
12 // 定义一个空切片
13 // insts := main([]*balance.Instance)
14 var insts []*balance.Instance
15 for i := 0; i < 16; i++ {
16 host := fmt.Sprintf("192.168.%d.%d", rand.Intn(255), rand.Intn(255))
17 one := balance.NewInstance(host, 8080)
18 insts = append(insts, one) // 自动对空切片进行扩容
19 }
20 // 选择负载均衡算法
21 var balanceName = "random"
22 if len(os.Args) > 1 {
23 balanceName = os.Args[1]
24 }
25 // var balancer balance.Balancer
26 // var conf = "random"
27 // if len(os.Args) > 1 {
28 // conf = os.Args[1]
29 // }
30 // if conf == "random" {
31 // balancer = &balance.RandomBalance{} // 随机
32 // fmt.Println("use random balancer")
33 // } else if conf == "roundrobin" {
34 // balancer = &balance.RoundRobinBalance{} // 轮询
35 // fmt.Println("use roundrobin balancer")
36 // }
37 // balancer := &balance.RandomBalance{} // 随机
38 // balancer := &balance.RoundRobinBalance{} // 轮询
39
40 for {
41 inst, err := balance.DoBalance(balanceName, insts)
42 if err != nil {
43 // fmt.Println("do balance err:", err)
44 fmt.Fprintf(os.Stdout, "do balance error\n")
45 continue
46 }
47 fmt.Println(inst)
48 time.Sleep(time.Second)
49 }
50
51}
52
53// 运行
54// go run go_dev/day7/example/example1/main random
55// go run go_dev/day7/example/example1/main roundrobin
56// go run go_dev/day7/example/example1/main hash
57// 编译
58// go build go_dev/day7/example/example1/main
59 |
main.go
反射
1. 反射:可以在运行时动态获取变量的相关信息
两个函数:
- a. reflect.TypeOf,获取变量的类型,返回reflect.Type类型
- b. reflect.ValueOf,获取变量的值,返回reflect.Value类型
- c. reflect.Value.Kind,获取变量的类别,返回一个常量
- d. reflect.Value.Interface(),转换成interface{}类型
2. reflect.Value.Kind()方法返回的常量
3. 获取变量的值:
1 2 3 4 5
| 1reflect.ValueOf(x).Float()
2reflect.ValueOf(x).Int()
3reflect.ValueOf(x).String()
4reflect.ValueOf(x).Bool()
5 |
4. 通过反射的来改变变量的值
1 2 3 4 5
| 1reflect.Value.SetXX相关方法,比如:
2reflect.Value.SetFloat(),设置浮点数
3reflect.Value.SetInt(),设置整数
4reflect.Value.SetString(),设置字符串
5 |
5. 用反射操作结构体
1 2 3
| 1a. reflect.Value.NumField()获取结构体中字段的个数
2b. reflect.Value.Method(n).Call来调用结构体中的方法
3 |
6.案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 1package main
2
3import (
4 "fmt"
5 "reflect"
6)
7
8type Student struct {
9 Name string
10 Age int
11 Score float32
12}
13
14func test(b interface{}) {
15 t := reflect.TypeOf(b)
16 fmt.Println(t)
17 v := reflect.ValueOf(b)
18 k := v.Kind()
19 fmt.Println(k)
20
21 iv := v.Interface()
22 stu, ok := iv.(Student)
23 if ok {
24 fmt.Printf("%v %T\n", stu, stu)
25 }
26}
27
28func testInt(b interface{}) {
29 val := reflect.ValueOf(b)
30 val.Elem().SetInt(100)
31
32 c := val.Elem().Int()
33 fmt.Printf("get value interface{} %d\n", c)
34 fmt.Printf("string value: %d\n", val.Elem().Int())
35}
36
37func main() {
38 var a Student = Student{
39 Name: "stu1",
40 Age: 18,
41 Score: 92,
42 }
43 test(a)
44 var b int = 1
45 testInt(&b)
46 fmt.Println(b)
47}
48 |
反射案例一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| 1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "reflect"
7)
8
9type Student struct {
10 Name string `json:"student_name"`
11 Age int
12 Score float32
13 Sex string
14}
15
16func (s Student) Print() {
17 fmt.Println("---start----")
18 fmt.Println(s)
19 fmt.Println("---end----")
20}
21
22func (s Student) Set(name string, age int, score float32, sex string) {
23
24 s.Name = name
25 s.Age = age
26 s.Score = score
27 s.Sex = sex
28}
29
30func TestStruct(a interface{}) {
31 tye := reflect.TypeOf(a)
32 val := reflect.ValueOf(a)
33 kd := val.Kind()
34 if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
35 fmt.Println("expect struct")
36 return
37 }
38
39 num := val.Elem().NumField()
40 val.Elem().Field(0).SetString("stu1000")
41 for i := 0; i < num; i++ {
42 fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind())
43 }
44
45 fmt.Printf("struct has %d fields\n", num)
46
47 tag := tye.Elem().Field(0).Tag.Get("json")
48 fmt.Printf("tag=%s\n", tag)
49
50 numOfMethod := val.Elem().NumMethod()
51 fmt.Printf("struct has %d methods\n", numOfMethod)
52 var params []reflect.Value
53 val.Elem().Method(0).Call(params)
54}
55
56func main() {
57 var a Student = Student{
58 Name: "stu01",
59 Age: 18,
60 Score: 92.8,
61 }
62
63 result, _ := json.Marshal(a)
64 fmt.Println("json result:", string(result))
65
66 TestStruct(&a)
67 fmt.Println(a)
68}
69 |
反射案例二