Go: 切片(Slice)
Slice
创建切片
数组与切片的区别
- 数组是值类型,编译时确定大小且拷贝时拷贝值,可以通过
[...]type{val1, val2}编译器自动推断长度 - 切片是引用类型,切片必须基于一个数组获得,对切片的操作会影响数组本身,因此也会影响同样共享该数组的切片
切割
数组切割是一个语法糖,类似其它语言的切片语法,返回切片类型
话虽如此,
go的切片比较简单,只支持自然数索引:1
2
3
4ns := [...]int{1, 2, 3, 4}
ns[1:] // [1, 4)
ns[:] // [0, 4)
ns[:len(ns)-1] // [0, 3)切片分割:与数组分割类似,数组和切片在默认时容量都是底层数组的长度减去
start更常用的是完整的
start:end:max表达式来防止切片影响原切片:1
2
3
4
5
6ns := [...]int{1, 2, 3, 4}
ns1 := ns[:]
// 指定容量为 max-start, 一般指定 max=end 即可
ns2 := ns1[1:2:2]
// 如果不指定容量则因没有爆容量而影响原切片
append(ns2, 1, 2)
使用make()预分配空间
直接使用
[]type创建无法预先指定其底层数组的空间使用
make()是常用的方法:1
ns := make([]int, len, cap)
len表示已经确认存在的值,并初始化为零值,cap为底层数组的容量实际上
len与cap是切片的基本组成属性
自动扩容
slice本身会自动扩容,重新分配到新的内存并指向它因此当基于数组/切片分割获取切片时,需要注意,在没有重新分配时对切片进行修改会影响原数组,在拼接后如果超出容量则不会影响原数组
最好的习惯是使用完整的
start:end:cap
切片转数组与解包
Go 1.17支持[LEN](s[:LEN])长度匹配的转换Go 1.20支持[LEN](s)省略切片符,要求len(s)>=LEN- 转换行为在内存上创建新的数组副本
- 切片能通过后跟
...解包,通常也用于作为可变参数传递
切片常用操作
内置函数
len(slice) int:获取长度cap(slice) int:获取容量append(slice []Type, elems ... Type):拼接切片,返回新切片对象并共用底层数组,不改变原切片copy(dst []Type, src []Type) int:拷贝数组,返回实际复制的元素个数,即min(len(dts), len(src))
衍生操作
- 删除指定元素:
s = append(s[:i], s[i+1:]...) - 删除连续元素:
s = append(s[:start], s[end:]...) - 插入指定元素:
s = append(s[:i], append([]T{v}, s[i:]...)...)