Go中的切片Slice
切片概念
切片是一种数据结构, 是一种动态数组, 按需自动改变大小, 可以方便的管理和使用数据集合
内部实现
- 切片基于数组实现的, 切片的底层是数组。
- 切片本身非常小, 是对数组的抽象
- 因为切片基于数组实现的, 所以底层的内存是连续分配的, 效率非常高
- 切片可以通过索引获得数据, 可以迭代以及垃圾回收优化
- 切片是对数组view的映射, 公用底层数组, 改变切片就会改变底层数组
切片声明和初始化
声明
-
make
方法, 单独参数, 既指定长度也指定容量 -
// 长度和容量都是5 slice := make([]int, 5) 复制代码
-
make
方法, 两个参数, 指定长度和容量 -
// 长度为5, 容量为10(容量对应底层数组) slice := make([]int, 5, 10) 复制代码
- 切片的底层为数组, 切片不指定值默认为零值
- 切片长度为5, 容量为10, 所以只能访问5个值
- 剩下5个元素需要切片扩充后才能访问
- 切片的容量必须 >= 切片的长度
-
使用
:=
创建切片// 此时切片的长度和容量都是5 slice:=[]int{1,2,3,4,5} 复制代码
-
使用
:=
创建部分切片// 此时切片的长度和容量都是5 slice:=[]int{4:1} 复制代码
-
数组和切片的区别
//数组 array:=[5]int{4:1} //切片 slice:=[]int{4:1} 复制代码
-
nil切片和空切片的区别, 他们的长度和容量都是0, 指向的底层数组不同
- nil切片指向底层数组的指针为nil, 表示不存在的切片
- 空切片指向的底层数组为指针为地址, 表示空切片集合
//nil切片 var nilSlice []int //空切片 slice:=[]int{} 复制代码
基于现有的数组或者切片创建切片
- 使用[i:j]来创建新的切片, i为索引开始, j为索引结束, 半开半闭区间, 包含i, 不包含j
- i 和 j 都可省略, 省略后默认为 0 和 len(slice) - 1
- 对于数组或者切片(容量为k)创建新的切片(slice[i:j])后的长度和容量为
长度为j - i
, 容量为k - i
- 系统内置方法长度为
len(slice)
, 容量为cap(slice)
使用第三个值来限制切片容量
- 创建了一个长度为
2 - 1 = 1
, 容量为3 - 1 = 2
- 第三个值不能超过原切片容量的最大值
slice := []int{1, 2, 3, 4, 5}
newSlice := slice[1:2:3]
复制代码
向切片追加值
- 通过
append
方法向切片追加值
slice := []int{1, 2, 3, 4, 5}
newSlice := slice[1:3]
newSlice=append(newSlice,10)
fmt.Println(newSlice)
fmt.Println(slice)
//Output
[2 3 10]
[1 2 3 10 5]
复制代码
- 通过
append
同时追加许多值
newSlice=append(newSlice,10,20,30)
复制代码
- 通过
...
和append
向切片中追加切片
slice := []int{1, 2, 3, 4, 5}
newSlice := slice[1:2:3]
newSlice = append(newSlice, slice...)
复制代码
- append函数会智能的增长底层数组的容量,目前的算法是:容量小于1000个时,总是成倍的增长,一旦容量超过1000个,增长因子设为1.25,也就是说每次会增加25%的容量。
迭代切片
- 使用
for range
迭代切片
slice := []int{1, 2, 3, 4, 5}
for i,v:=range slice{
fmt.Printf("索引:%d,值:%d\n",i,v)
}
复制代码
- 也可以使用
for
迭代切片
slice := []int{1, 2, 3, 4, 5}
for i := 0; i < len(slice); i++ {
fmt.Printf("值:%d\n", slice[i])
}
复制代码
注意点
range
返回的是切片元素的复制, 不是元素的引用
在函数中传递切片
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Printf("%p\n", &slice)
modify(slice)
fmt.Println(slice)
}
func modify(slice []int) {
fmt.Printf("%p\n", &slice)
slice[1] = 10
}
复制代码
注意点
- 传递复制切片时, 底层数组不会被复制, 也不会收影响, 复制只是复制的切片本身, 不涉及底层数组