<Go>4 数组、切片和 map
本文最后更新于:2023年6月27日 上午
4 数组、切片和 map
4.1 数组
数组可以存放多个同一类型的数据。数组也是一种数据类型。
在 Go 中,数组也是值类型。默认情况下为值拷贝,新旧数组互不影响
数组在内存中是一段连续的空间。数组名指向该数组空间的首地址,也是数组第一个元素的地址。
数组各个元素的地址间隔依据数组类型决定。
Go 中不允许可变大小的数组,也不允许使用变量作为数组大小。如有需求,请使用切片
数组的定义:
var array [10]int // 数组元素为零值
var array1 [3]int = [3]int{1, 2, 3} // 声明时即初始化
var array2 = [3]int{1, 2, 3} // 类型推导
var array3 = [...]int{1, 2, 3, 4} // 数组大小推导
var array4 = [4]int{1: 1, 0: 2, 3: 3, 2: 4} // 指定那些下标元素
var array5 = [...]int{1: 1, 0: 2, 3: 3, 7: 4} // 此时类型为 int[8]
访问数组元素:
数组名[下标]
4.2 切片
slice 切片是 Go 中特有的数据类型。切片的使用类似数组
切片是数组的引用,因此切片是引用类型。进行值传递时,遵守引用传递机制
切片的长度可变,因此切片是可以动态变化的数组
#切片的定义:
var s []int // 声明一个切片
s1 := array4[1:3] // 该切片引用数组 array4 [1,3) 范围的数据
s2 := make([]int, 4, 10) // 使用 make 函数获得 长度4 容量10 的切片
s3 := make([]int, 5) // 该切片容量、长度都是 5
s4 := array4[2:] // 相当于 array4[2:len(array4)]
s5 := array4[:4] // 相当于 array4[0:4]
s6 := array4[:] // 相当于 array4[0:len(array4)]
切片声明后还不能使用,因为其为空。必须让其引用数组,或使用 make 方法产生切片空间后才能使用。
切片可以继续切片
#切片常用函数:
-
len(v) int
:返回切片的长度(包含的元素数量) -
cap(v) int
:返回切片的容量(能包含的最大元素数量) -
make(Type, IntegerType) Type
:分配并初始化一个指定长度的切片make(Type, IntegerType, IntegerType) Type
:返回一个指定长度、容量的切片通过 make 方式创建的切片,其对应数组由 make 函数底层维护,对外不可见。
-
append(slice []Type, ele Type...) slice
:对切片进行动态追加。容量不足的场合会扩容。返回追加完毕后的新的切片
Go 底层会创建新的数组,并将原有元素以 值拷贝 方式拷贝到新的数组。之后,返回一个引用新数组的新切片
也就是说,切片进行 append 后,新的切片会失去对原有数组的引用
也能追加一个切片:
s = append(s, s...) // 表示将 s 的全部元素追加到 s 后
-
copy(s []Type, o []Type)
:将 o 的数据拷贝(值拷贝)到 s。期间,s 的容量不变。s 容量更大时,多余位置保留原样。s 容量更小时,其余元素不保存。
#string 与 slice 的关系
因为 string 底层是 byte 数组,因此 string 也能进行切片处理
字符串是不可变的。不能通过下标直接改变 string 的字符。可以通过切片实现修改需求
想要改变字符串时,先将字符串转换成 []byte 或 []rune。修改后重新转换成字符串:
str := "刻晴刻晴刻晴刻晴"
s := []rune(str)[6:]
s = append(s, []rune("晴~~")...)
s[3] = '★'
str = string(s) // 刻晴晴★~
4.3 map
map(映射)是 key-value 数据结构,又称字段或关联数组
key 可以是 slice、map、function 外的类型(这些类型不能使用 == 判断)。通常使用 int 或 string 做 key
#map 的定义:
var m map[string]int // key 是 string,value 是 int
m2 := make(map[string]int, 10)
m3 := map[int]string{
0: "刻晴",
1: "胡桃",
2: "甘雨",
}
map 的声明时不分配内存,需要 make 后才能使用
#map 的 CRUD:
m["刻晴"] = 100 // 增加、修改 k-v
delete(m, "刻晴") // 按照 key 删除 k-v
val, find := m["甘雨"] // val 为查找到的值,find 为是否找到
for k, v := range m { // 使用 for-range 进行遍历
fmt.Println(k, " - ", v)
}
map 的 key 不能重复,value 可以重复。其 key - value 是无序存放的
要将 map 的 key 排序,只有先将所有 key 取出,再将取出的 key 排序,最后按照顺序取出那些值
#使用细节
- map 是引用类型,遵守引用传递的机制
- map 的容量达到后,会自动扩容
- map 的 value 也常用 struct 类型,更适合管理复杂数据