Go容器
go 容器用三种: 数组(Array) 、切片(Slice)、映射(map)
1. 数组 Array
数组:是一个长度固定,用于存储一段具有相同类型元素的连续块。
在 Go 开发中一般不直接使用数组,而是使用切片,数组是定长的,不可扩展,切片相当于动态数组,使用场景多。
func opArray() {
var arr1 [3]int // [0 0 0] 声明数组,不赋初值(使用默认值)
arr2 := [3]int{1, 2, 3} // [1 2 3]// 字面量声明数组,赋初值
arr3 := [...]int{1, 2, 3, 4, 5} // [1 2 3 4 5] // 容量由初始化值的数量决定,...不可省略,不带长度或者 ... 的表示切片
arr1[0] = 1
fmt.Println(arr1[0])
fmt.Println(arr1, arr2, arr2)
//只有数组的类型相同,容量一样,两个数组才能相互赋值
arr1 = arr2 //正确
arr1 = arr3 //错误
}
2. 切片
切片是一种数据结构,这种数据结构便于管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数 append 来实现的。这个函数可以快速且高效地增长切片。还可以通过对切片再次切片来缩小一个切片的大小。
切片是一个很小的对象,对底层数据进行了抽象,并提供相关的操作方法。切片有三个字段:分别是指向底层数组的指针、切片访问的元素的个数(即长度len)和切片允许增长到的元素个数(即容量cap)
切片共享底层数据
func opSlice() {
s1 := make([]int, 3) // 创建一个整型,容量、长度为3的切片
s2 := make([]string, 1, 5) // 创建一个整型,容量为5,长度为1的切片
s3 := []string{"java", "go", "js"} // 切片字面量声明切片
var s4 []int //创建nil整型切片
s6 := s3[0:] //"java", "go", "js"
s7 := s3[1:2] // "go"
#append 增加切片长度
s := []int {20 , 30, 40}
s4 = append(s4, 10) //10
s4 = append(s4, s...)//10,20,30,40
s4 := append(s4, s[2:])//10,20,30,40,40
s4[0] = 0 //0,20,30,40,40
当切片没有足够的可用容量,再追加需要扩容,此处会新建一个新的底层数组,然后将旧数组元素拷贝到新数组,而原slice的底层数组是旧数组,此时二者互不影响;
slice 扩容机制:在切片的容量小于 1000 个元素时,总是会成倍地增加容量。一旦元素个数超过 1000,容量的增长因子会设为 1.25,也就是会每次增加 25% 的容量;
由于切片共享底层数据,所以我们对切片的修改可能会影响多个切片。
//切片迭代
s := []int{1,2,3,4,5}
for i, v := rang s {
fmt.Println(i, v)
}
3. Map 映射
映射是一种数据结构,用于存储无序的键值对。
func opMap() {
// 使用 make 创建 map,key为string,value为string
mp1 := make(map[string] sring)
// 使用 make 创建 map,key为string,value为int
mp2 := make(map[string] int)
//使用字面量创建 map - 最常用的姿势,定义并赋值
m3 := map[string]string{"hello":"xhb","word","qq"}
// 创建空映射
m4 := map[string]string{} // m4 := map[string]string nil映射
}
//增加
m3["lg"] = "go"
//删除
delete(m3, "hello")
//取值
v, ok := lessons["lg"]
if ok {//存在
fmt.Println(v)
} else {
fmt.Println("key not exist")
}
//迭代
for k, v := rang m3 {
fmt.Println(k, v)
}