上篇分为2部分:
- 结构体、函数、程序流程控制、结构体标签
- 包、变量、常量、指针、数据结构、反射
结构体、函数defer、程序流程控制
1 OOP:Go不是面向对象语言,但是具有OOP的特性,体现了很大的灵活性。
1. 封装:结构体(属性)+ 构造器(New开头,返回一个对象地址)+ 方法(绑定结构体)
- 注意指针:*是声明类型,&是取地址,都表示指针地址(记住&表示对象即可)
- 注意命名:结构体的类、属性、方法的命名,决定访问权限,一般都大写。
- go的结构体本质上是创建指针。因此外部创建对象返回的是对象地址(&r),而内部属性的使用要用this这个对象去调用,在方法传参时要传递对象地址(&r)。
- 构造方法: NewAccount() *Account,New开头,返回一个对象地址。
2. 继承:组合
- 声明:属性加上父类即可,可以重写、独创。
- 创建:嵌套父类的形参列表。
3. 多态:接口
- 声明:实现接口的所有方法就行。
- 创建:要加&子类!
2 函数、defer
1. 写法:
- 定义函数时,先考虑传参和给返回值,不要漏了() !
- go的函数定义是返回值放在形参列表后面,而且是多形参、多返回值。
- 形参列表就相当于定义了变量,因此在函数体内要用赋值符号(=)。
2. defer是结束程序的最后一步,通常用于关闭Close(),后于return。
3 程序流程控制
- 循环全部用for。for{}是死循环。
- break用于退出循环,return用于退出程序,continue用于重新开始下一轮(一般是好几轮)
- switch的case不用break。
4 结构体标签(一般不会手动编码解码,自动),用于其他包调用时能看到属性的说明(避免二义性)。
func findTag(str interface{}) {
// 1. 获取全部元素的类型:TypeOf获取类型,Elem()全部元素
t := reflect.TypeOf(str).Elem()
// 2. 遍历全部字段数量次
for i := 0; i < t.NumField(); i++ {
// 3. 获取字段:第i行,Tag获取标签,Get获取标签内的字段(key: "info","doc")
taginfo := t.Field(i).Tag.Get("info")
tagdoc := t.Field(i).Tag.Get("doc")
// 4. 打印字段
fmt.Println("info: ", taginfo, ", doc: ", tagdoc)
}
}
接收与输出
接收要先声明再传入地址,格式化输出用占位符,格式化返回用变量接/匿名。
1. 接收scanln:一定要先声明,再接收地址。
var choose int // 声明
fmt.Scanln(&choose) // 传入scanln地址
fmt.Scanf("%s\n%s",&a,&b) // 格式化
2. 普通输出:println
1. 格式化输出:printf(format, ...)
2. 占位符:%T数据类型, %s字符串, %d整数, %v数据的值, %t布尔值
3. 字符串连接: ,(不能用+)
3. 格式化返回(不输出):sprintf,一般用一个变量接收。
包、变量、常量、指针、数据结构、反射
0 包可以匿名、别名、用 . 直接导入本包(不建议可能造成方法重载)。
1 变量:go的数据类型声明在变量名后面,有三种声明语法。
go的数据类型:int,string,float32,float64,struct。
原则:go的所有包、变量声明了就必须使用,否则报错。可以用_匿名代表。
- 具体赋值:{...}
- 只声明:var A
- 省略var和数据类型: :=
- 声明多个变量,类型一样可合并。
2 常量:const可以用于枚举,iota用于累加计算,第一行默认iota=0。
3 指针:值传递和引用传递
-
go默认是值传递(包括struct)。如果要改变原值就要加上*。(比如结构体的属性,是需要被用户修改的,因此就需要传入地址 (this *Hero))
-
slice、map、channel天生是引用传递。
-
这些数据结构要注意空指针现象,不能只声明,不然没有分配空间,否则为nil。
-
如果要独立,不想改变原值,就make一个新的来调用。
-
4 数据结构:array、slice、map、channel、interface{}
1. 定义:
- 数组类型是[10]int,切片类型是[]int。
- 数组类型包含了长度,因此在方法传参上有限制。( [10]int )
2. slice、map、channel天生就是指针。因此如果只声明不赋值的话,就是空指针,没有被分配空间。(判断slice是否为空:if slice == nil)
3. 声明:
- 具体赋值:{...}
- 只声明(接收用户输入时经常用到):var
- 只分配空间(初始化属性时经常用到):make([]int, 3)
4. 操作:
- for的两种常用遍历方式:索引遍历(for),元素遍历(for key/index, value := range nums)
- slice切片长度,容量
- 直接赋值
- append是追加,在ptr后一位添加。
- 满了会动态扩容。
- slice切片截取:默认指向同一对象(本质是指针)。要独立就要make新的。
- map添加/修改:直接赋值(索引是key)。
- map删除:delete(索引是key)。
5. Go的泛型就是一个万能接口interface{}。
- 方法传参:万能类型变量arg,类型为空接口interface{}。
- 类型断言:value, ok := arg.(string)(注意:arg.要加点!)
5 反射
1. 每个变量有一对pair,pair会连续传递。(反射:变量 --> pair)
- type(二选一:静态类型static。具体类型concrete(interface具体指向的类型))
- value。
2. reflect包可用于获取类型和值,TypeOf(), ValueOf()。