目录
一、定义:
切片是一个拥有相同类型元素的可变长度的序列。
二、切片的结构:
type SliceHeader struct {
Data uintptr //第一个是字符串指向的底层字节数组,
Len int //第二个是字符串的字节的长度
Cap int //切片指向的内存空间的最大容量(对应元素的个数不是字节数)
}
三、声明方式:
var name [] T
T : 表切片元素类型,可以是整型、浮点型、布尔型、切片、map 、函数等。
切片的元素使用“ [] ”进行访问,在方括号中提供切片的索引即可访问元素,索引的范围从 0开始,且不超过切片的最大容量。
代码如下:
a := make([]int , 3) //创建一个容量为 整型切片。
a[0] = 1 //为切片元素赋值。
其他方式:
var (
a []int // nil切片, 和 nil 相等, 一般用来表示一个不存在的切片
b = []int{} // 空切片, 和 nil 不相等, 一般用来表示一个空的集合
c = []int{1, 2, 3} // 有3个元素的切片, len和cap都为3
d = c[:2] // 有2个元素的切片, len为2, cap为3
e = c[0:2:cap(c)] // 有2个元素的切片, len为2, cap为3
f = c[:0] // 有0个元素的切片, len为0, cap为3
g = make([]int, 3) // 有3个元素的切片, len和cap都为3
h = make([]int, 2, 3) // 有2个元素的切片, len为2, cap为3
i = make([]int, 0, 3) // 有0个元素的切片, len为0, cap为3
)
和数组一样,内置的 len 函数返回切片中有效元素的长度,内置的 cap 函数返回 切片容量大小,容量必须大于或等于切片的长度。也可以通过 reflect.SliceHeader 结构访问切片的信息(只是为了说明切片的结构,并不是推荐的做法)。切片可以和 nil 进行比较,只有当切片底层数据指针为空时切片本身为 nil ,这时候切片的长度和容量信息将是无效的。如果有切片的底层数据指针为空,但是长度和容量不为0的情况,那么说明切片本身已经被损坏了(比如直接通过 reflect.SliceHeader 或 unsafe 包对切片作了不正确的修改)。
四、拓展
(1)、切片还可以在其元素集合内连续地选取一段区域作为新的切片 就像其名字“切片”
样,切 一块区域,形成新的切片 。
(2)、遍历同数组。
五、添加切片元素、删除切片元素
1、添加切片元素
(1)、尾部追加
内置的泛型函数 append 可以在切片的尾部追加 N 个元素:
var a []int
a = append(a, 1) // 追加1个元素
a = append(a, 1, 2, 3) // 追加多个元素, 手写解包方式
a = append(a, []int{1,2,3}...) // 追加一个切片, 切片需要解包
不过要注意的是,在容量不足的情况下, append 的操作会导致重新分配内存,可
能导致巨大的内存分配和复制数据代价。即使容量足够,依然需要用 append 函数
的返回值来更新切片本身,因为新切片的长度已经发生了变化。
(2)、开头添加元素
var a = []int{1,2,3}
a = append([]int{0}, a...) // 在开头添加1个元素
a = append([]int{-3,-2,-1}, a...) // 在开头添加1个切片
在开头一般都会导致内存的重新分配,而且会导致已有的元素全部复制1次。因此,从切片的开头添加元素的性能一般要比从尾部追加元素的性能差很多。
2、删除切片元素
根据要删除元素的位置有三种情况:从开头位置删除,从中间位置删除,从尾部删 除。其中删除切片尾部的元素最快:
a = []int{1, 2, 3}
a = a[:len(a)-1] // 删除尾部1个元素
a = a[:len(a)-N] // 删除尾部N个元素
删除开头的元素可以直接移动数据指针:
a = []int{1, 2, 3}
a = a[1:] // 删除开头1个元素
a = a[N:] // 删除开头N个元素
删除开头的元素也可以不移动数据指针,但是将后面的数据向开头移动。可以 用 append 原地完成(所谓原地完成是指在原有的切片数据对应的内存区间内完 成,不会导致内存空间结构的变化):
a = []int{1, 2, 3}
a = append(a[:0], a[1:]...) // 删除开头1个元素
a = append(a[:0], a[N:]...) // 删除开头N个元素
也可以用 copy 完成删除开头的元素:
a = []int{1, 2, 3}
a = a[:copy(a, a[1:])] // 删除开头1个元素
a = a[:copy(a, a[N:])] // 删除开头N个元素
对于删除中间的元素,需要对剩余的元素进行一次整体挪动,同样可以 用 append 或 copy 原地完成:
a = []int{1, 2, 3, ...}
a = append(a[:i], a[i+1:]...) // 删除中间1个元素
a = append(a[:i], a[i+N:]...) // 删除中间N个元素
a = a[:i+copy(a[i:], a[i+1:])] // 删除中间1个元素
a = a[:i+copy(a[i:], a[i+N:])] // 删除中间N个元素