2022-5-16 实习Day37

1、黑名单校验未命中问题排查,项目黑名单url失效 –3小时 100%
2、协助测试,测试问题帮助解答–3小时 100%

Golang编程学习(part 32)

1、接口编程的最佳实践

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 实现对Hero结构体切片的排序: sort.Sort(data Interface)
package main

import (
"fmt"
"math/rand"
"sort"
)

// 1、声明Hero结构体
type Hero struct {
Name string
Age int
}

// 2、声明一个Hero结构体切片类型
type HeroSlice []Hero

// 3、实现Interface接口
func (hs HeroSlice) Len() int {
return len(hs)
}

// Less方法就是决定你使用什么标准进行排序
// 按Hero年龄从小到大排序
func (hs HeroSlice) Less(i, j int) bool {
return hs[i].Age < hs[j].Age

// 修改成对Name排序
// return hs[i].Name<hs[j].Name
}

func (hs HeroSlice) Swap(i, j int) {
// 交换
hs[i], hs[j] = hs[j], hs[i]
}

// 声明Student结构体
type Student struct {
Name string
Age int
Score float64
}

// 将Student的切片,按Score从大到小排序
func main() {
// 先定义一个数组/切片
var intSlice = []int{0, -1, 10, 7, 90}

// 要求对intSlice切片进行排序
// 冒泡排序
// 也可以使用系统提供的方法
sort.Ints(intSlice)
fmt.Println(intSlice) // [-1 0 7 10 90]

// 测试看看我们是否可以对结构体切片进行排序
var heros HeroSlice
for i := 0; i < 10; i++ {
hero := Hero{
Name: fmt.Sprintf("英雄|%d", rand.Intn(100)),
Age: rand.Intn(100),
}

// 将hero append 到heros切片
heros = append(heros, hero)
}

// 看看排序前的顺序
for _, v := range heros {
fmt.Println(v)
}

//调用sort.Sort
sort.Sort(heros)
fmt.Println("------------排序后---------------")
// 看看排序后的顺序
for _, v := range heros {
fmt.Println(v)
}

}

[-1 0 7 10 90]
{英雄|81 87}
{英雄|47 59}
{英雄|81 18}
{英雄|25 40}
{英雄|56 0}
{英雄|94 11}
{英雄|62 89}
{英雄|28 74}
{英雄|11 45}
{英雄|37 6}
------------排序后---------------
{英雄|56 0}
{英雄|37 6}
{英雄|94 11}
{英雄|81 18}
{英雄|25 40}
{英雄|11 45}
{英雄|47 59}
{英雄|28 74}
{英雄|81 87}
{英雄|62 89}

2、实现接口 vs 继承

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
package main

import "fmt"

// Monkey结构体
type Monkey struct {
Name string
}

// 声明接口
type Birdable interface {
Flying()
}

type Fishable interface {
Swimming()
}

func (m Monkey) climbing() {
fmt.Println(m.Name, "生来会爬树...")
}

// LittkeMonkey结构体
type LittkeMonkey struct {
Monkey // 继承
}

// 让LittkeMonkey实现BirdAble
func (lm *LittkeMonkey) Flying() {
fmt.Println(lm.Name, "通过学习,会飞翔...")
}

// 让LittkeMonkey实现FishAble
func (lm *LittkeMonkey) swimming() {
fmt.Println(lm.Name, "通过学习,会游泳...")
}

func main() {
// 创建一个LittkeMonkey实例
monkey := LittkeMonkey{
Monkey{Name: "悟空"},
}
monkey.climbing()
monkey.Flying()
monkey.swimming()
}

对上面代码的小结

1)当A结构体继承了B结构体,那么A结构体就自动继承了B结构体的字段和方法,并且可以直接使用

2)当A结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口接口,因此我们可以认为:实现接口是对继承机制的补充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
          |----------------|                   |----------------|
| 运动员 | | 学生 |
| | | |
| | | |
|----------------| |----------------|
/|\ /|\ /|\ /|\
| | | |
| | | |
|----------------| |----------------| |-----------| |-----------|
| | | | | | | |
| 篮球运动员 | | 足球运动员 | | 大学生 | | 中学生 |
| | | | | | | |
|----------------| |----------------| |-----------| |-----------| | |
| |
\|/ \|/
|-------------------|
| 学习英语的技能 |
| (接口) |
|-------------------|

① 接口和继承解决的问题不同

1)继承的价值主要在于:解决代码的复用性可维护性

2)接口的价值主要在于:设计,设计好各种规范(方法),让其他自定义类型去实现这些方法

② 接口比继承更加灵活:继承是满足is-a的关系,而接口只需要满足like-a的关系
③ 接口在一定程度上实现代码解耦