2022-5-9 实习Day31

1、行内汇款核心记账失败问题排查,数据库账号未加概述 –2小时 100%
2、行内汇款任务结束,自动发起汇入汇款部分信息未显示,前置任务为填写。–2小时 100%
3、工作流报错,测试等待复测。–2小时 90%

Golang编程学习(part 26)

1、struct类型的内存分配机制

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
var p1 Person
p1.Age = 10
p1.Name = "小明"

var p2 Person = p1

p2.Name = "小张"
fmt.Println(p1)
fmt.Println(p2)

{小明 10}
{小张 10}

画内存图:
________
| 小明 |
p1————>|_______|
| 10 |
|_______|
________
| 小张 |
p2————>|_______|
| 10 |
|_______|

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
var p1 Person
p1.Age = 10
p1.Name = "小明"

var p2 *Person = &p1
p2.Name = "小红"
fmt.Println(p1) // {小红 10}
fmt.Println(*p2) // {小红 10}

fmt.Printf("p1的地址: %p\n", &p1) // p1的地址: 0xc000004078
fmt.Printf("p2保存的地址: %p\n", p2) // p2保存的地址: 0xc000004078
fmt.Printf("p2本身的地址: %p\n", &p2) // p2本身的地址: 0xc000006028

画内存图:
0xc000004078
________
| 小明 |
p1————>|_______| <——————————————
| 10 | |
|_______| |
|
0xc000006028 |
______________ |
| | |
p2————>| 0xc000004078 |—————————
|______________|


1
2
3
4
5
6
7
8
9
// 看下面代码,分析原因
var p1 Person
p1.Age = 10
p1.Name = "小明"
var p2 *Person = &p1
fmt.Println(*p2.Age)

// 能不能像上面这样写?
// 不能啊!!! 因为 . 的运算符优先级比 * 高

2、结构体使用注意事项和细节

① 结构体中的所有字段在 内存中是连续
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
type Point struct {
x int
y int
}

type Rect struct {
leftUp, rightDown Point
}

type Rect2 struct {
leftUp, rightDown *Point
}

func main() {
r1 := Rect{Point{10, 20}, Point{30, 40}}

// r1有四个int,在内存中是连续分布的
// 打印地址
fmt.Printf("r1.leftUp.x地址:%p\nr1.leftUp.y地址:%p\nr1.rightDown.x地址:%p\nr1.rightDown.y地址:%p\n",
&r1.leftUp.x,
&r1.leftUp.y,
&r1.rightDown.x,
&r1.rightDown.y)

fmt.Println()

// r2有两个 *Point 类型,这两个 *Point 类型的本身地址也是连续的。
// 但是他们指向的地址不一定连续
r2 := Rect2{&Point{20, 30}, &Point{40, 50}}
fmt.Printf("r2.leftUp.x地址:%p\nr2.leftUp.y地址:%p\nr2.rightDown.x地址:%p\nr2.rightDown.y地址:%p\n",
&r2.leftUp.x,
&r2.leftUp.y,
&r2.rightDown.x,
&r2.rightDown.y)

fmt.Println()

fmt.Printf("r2.leftUp地址:%p\nr2.rightDown地址:%p\n",
&r2.leftUp,
&r2.rightDown)

fmt.Println()

// 指向的地址不一定连续哦!!!这要看系统如何分配
fmt.Printf("r2.leftUp指向的地址:%p\nr2.rightDown指向的地址:%p\n",
r2.leftUp,
r2.rightDown)

}

r1.leftUp.x地址:0xc00000e2c0
r1.leftUp.y地址:0xc00000e2c8
r1.rightDown.x地址:0xc00000e2d0
r1.rightDown.y地址:0xc00000e2d8

r2.leftUp.x地址:0xc0000160d0
r2.leftUp.y地址:0xc0000160d8
r2.rightDown.x地址:0xc0000160e0
r2.rightDown.y地址:0xc0000160e8

r2.leftUp地址:0xc000058250
r2.rightDown地址:0xc000058258

r2.leftUp指向的地址:0xc0000160d0
r2.rightDown指向的地址:0xc0000160e0

② 结构体是用户单独定义的类型,和其他类型进行转换时需要有完全相同的字段 (名字,个数和类型)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type A struct {
Num int
}

type B struct {
Num int
}

func main() {
var a A
var b B
a = A(b)
fmt.Println(a, b)
}

{0} {0}

③ 结构体进行 type 重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转
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
type Student struct {
Name string
Age int
}

type Stu Student

type integer int

func main() {
var stu1 Student
var stu2 Stu

// 类型不同,赋不了值
// stu2 = stu1

//但可以这样修改
stu2 = Stu(stu1)
fmt.Println(stu1, stu2)

var i int = 20
var j integer = 10
// 这样也是不正确的,类型不同
// j=i
fmt.Println(i, j)
}

{ 0} { 0}
20 10

④ struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Skill string `json:"skill"`
}

func main() {
// 1、创建一个Monster变量
monster := Monster{"牛魔王", 999, "芭蕉扇~"}

// 2、将monster变量序列化为 json格式字符串
// json.Marshal 函数中使用反射,这个讲解反射时,会详细介绍
jsonstr, err := json.Marshal(monster)
if err != nil {
fmt.Println("json处理错误", err)
}
fmt.Println("jsonstr=", string(jsonstr))
}

jsonstr= {"name":"牛魔王","age":999,"skill":"芭蕉扇~"}