-
Notifications
You must be signed in to change notification settings - Fork 0
/
04、进阶
170 lines (103 loc) · 4.1 KB
/
04、进阶
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
指针
Go 有指针,一个指针类型这样定义 *<类型>
任何一个没有赋值的指针的值都为 nil
若要在指针内存储一个对象的地址,需要使用 & 操作符取对象的地址
若要取出一个指针所指向的值,可以在指针变量名前加 *
EG.
var p *int // 声明了一个指向 int 类型的指针 p
fmt.Println(p) // 打印了 nil,也就是指针类型变量的初始值
var i int
p = &i // 用 & 取了 整数型变量 i 的地址,并存储到 p 中
fmt.Println(p) // 打印出了一个十六进制数,代表 p 存储的内存地址
v = *p // 通过对指针变量名前加 * ,取出 指针 指向的数据值
fmt.Println(v) // 打印出 0,也就是 上述 i 的值
*p = 8 // 通过指针取值,直接修改原数据值
fmt.Println(i) // 已修改原变量 i 的值为 8
fmt.Println(*p) // *p 的值自然为 8
fmt.Println(v) // 保存的是修改前的值,为 0
内存分配
Go 语言中,有 GC 机制,我们不需要要手动管理内存回收
Go 语言中,内存用 new 和 make 两个内建函数来分配
new
语法 new(<类型>)
new 用于分配内存给指定类型,并用该类型的零值填充该内存区域,
并返回指向该内存的地址,一个 *<类型> 的指针
make
语法 make(<类型>[,<长度>][,<容量>])
make 用于为 slice、map、channel 三种类型分配内存
并返回生成的对象
本质上来说,slice map 和 channel 在分配内存之后,都需要做初始化处理
make 的作用就是在分配内存后,还做了一系列初始化动作
定义新类型
type <新类型名称> <新类型数据结构>
EG.
type MyInt int // 一个底层为 int 类型的 MyInt 类型
与新类型常连用的是称为 结构体类型,来定义复杂类型
结构体
结构体的声明
struct {
[<字段名称>] <字段对应的类型>
...
}
eg1.
type Person struct{ // 声明了一个新的类型 Person,它是一个结构体
// 该类型的类型名大写,是可导出新类型
uuid string // 结构体里包含的字段1:uuid,类型为 string
// 由于首字母是小写,所以是非导出字段
Id int // 以下字段都是可导出字段
Name string
Phone int
Address string
string // 匿名字段,其类型为 string,而字段名随着类型,也叫做 string
} // 注意,无论是匿名字段还是非匿名字段,都不可以重名
结构体中字段的赋值
1、字面值赋值
<结构类型名>{
<字段名a>:<值a>, // 可乱序排列,但不可忽略字段名
...
}
或者
<结构类型名>{
<值1>, // 可忽略字段名,但不可乱序排列
...
}
2、类 OO 赋值,该方法也是取用字段名对应的值的方法
<结构对象名>.<字段名> = <值>
eg2.
// 接 eg1
var p1 Person = Person{
uuid:1234-1234-12341234-1234,
string:"Wow!FirstMan!", // 有字段名即可乱序赋值
Phone:1234567890,
}
p2 := Person{
1234-1234-12341234-1234, // 不乱序可省略字段名
001,
"XA",
"Wow! A Place",
}
var p3 Person
p3.Name = “NNa” // 调用修改
有关于结构体中,匿名字段的名称问题
struct{
T1 // 名称为 T1
*T2 // 名称为 T2
P.T3 // 名称为 T3
}
方法
有一类特殊的函数,它们与某种类型绑定,是某种类型专有的函数,它们被称为 方法
eg3.
// 接 eg1
func (p *Person) ChangeName(newName string){ // 接受一个 Person 类型的指针
p.Name = newName // 此处 (*p).Name 可以简写为 p.Name
}
// 使用方法
var p1 *Person // 建立一个对象
p1.ChangeName("AAAA") // 调用对象的方法
一个方法绑定的类型,必须是本地包定义的类型,不可以是导入包的类型,或者内建类型
有一些特殊的方法名,在 Go 语言中具有特定的意义,不要把不相关的功能定义为这些方法名
它们包含:
Read、Write、Close、Flush、String 等等
同样的,若一个方法实现了中所周之的方法,则使用相同的方法名
比如 被 fmt 包调用的 String 方法就是类型转字符的标准方法名
在 Go 中,所有的类型转换必须是显式的(必须由代码指明转换)