四种复合数据类型:数组、slice、map和结构体,数组和结构体长度是固定的,slice和map都是动态的
数组
数组是具有固定长度且拥有零个或者多个相同数据类型元素的序列
声明 var q [3]int = [3]{1, 2, 3} 或 q := […]int{1,2,3}
知识点:
- 数组的长度是数组类型的一部分,所以[3]int和[4]int是两种不同的数组类型
- 如果一个数组的元素类型是可比较的,那么这个数组也是可比较的
- Go把数组和其他类型都看成是指传递,若想用引用传递,需要显示地传递一个数组指针
slice
slice表示一个拥有相同类型元素的可变常度的序列,通常写成[]T
声明 var q []int
知识点:
- slice可以用来访问数组的部分或全部元素,而这个数组是slice的底层数组
- slice有三个属性:指针、长度和容量
- 指针指向第一个可以从slice中访问的元素,这个元素不一定是数组的第一个元素
- 长度是指slice中的元素的个数,不能超过容量
- 容量是指从slice的起始元素到底层数组的最后一个元素间元素的个数
- 一个底层数组可以有多个slice
- slice操作符s[i:j]创建一个新的slice
- 如果slice引用超过了被引用对象的容量,会报错
- slice包含了底层数组的指针,所以在传参时,函数内可以修改底层数组的元素
- slice不能进行比较
- slice的零值是nil,没有底层数组
- make可以创建一个具有指定元素类型、长度和容量的slice,该方法会创建一个无名数组
- appendInt,每次调用都会检查slice是否有足够的容量,如果容量不足,则创建一个新的足够容量的底层数组,每次扩展一倍的容量。
- 只要有可能改变slice的长度或者容量,或者指向新底层数组时,需要更新slice变量
map
map是一个拥有键值对的无序集合,
声明:ages := make(map[string]int) 或 var ages map[string]int
知识点:
- map中所有的键类型必须相同,所有的值类型必须相同,但键和值得类型可以不相同
- 键的类型k必须是可以通过操作符==号来比较的数据类型
- 使用map的键查找的元素不存在时,返回值类型的零值
- map元素不是一个变量,不可以获得它的地址
- map中元素迭代顺序是不固定的
- 若需要顺序访问map,则需要显示的给键排序,然后按排序顺序通过键访问值
- 不能给零值map设置元素,map设置元素前必须初始化
- map中的元素输出两个值,第二个值是一个布尔值,用来报告元素是否存在,需要和零值区分
- map值类型本身可以是复合数据类型
结构体
结构体是零个或多个任意类型的命名变量组合在一起的聚合数据类型,每个变量都是结构体的成员
定义结构体:先声明,后定义
知识点:
- 结构体成员通过点号访问
- 成员变脸的顺序对于结构体同一性很重要,有相同变量不同变量顺序结构体不是同一个结构体
- 结构体成员变量名称首字母大写为可导出,小写为不可导出
- 结构体类型s不可以包含相同类型s的成员变量,但可以包含一个s的指针类型
- 结构体的零值由成员的零值构成
- 没有成员的结构体为空结构体
- 结构体字面量设置结构体,type Point struct{X , Y int}
- Go是按值调用的语言,调用函数接收到的是实参的一个副本,不是引用
- 结构体嵌套机制
- go允许定义不带名称的结构体成员,称为匿名成员
- 结构体嵌套机制可以直接访问内嵌结构体成员
JSON
json中的数据类型的格式
知识点:
- 把go的数据结构转换为JSON称为marshal,无编排输出
- MarshalIndent有编排输出
- 只有可导出的成员可以转换成JSON字段
- json定义成员标签:
- unmarshal将JSON转换成go数据结构
- 即使对应的JSON字段的名称不是首字母大写,结构体成员名称也必须首字母大写
- json.Decoder流式解码器,可以利用它依次从字节流里面解码多个JSON实体
- json.Encode流式编码器
文本和HTML模板
模板是一个字符串或者文件,它包含一个或者多个两边用双大括号包围的单元{{…}}(称为操作)
- 每个操作在模板里对应一个表达式
- 在操作里面,有一个表示当前值得标记,用点号(.)表示{{ .Count }}表示Count的值,直接输出
- 在操作中符号 | 会将前一个操作的结果作为下一个操作的输入,类似shell中的管道