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