切片的定义和属性
保存一组数据,但是数据的个数不确定时,使用切片(数组的大小是固定的,可以将切片看作的可以变化大小的数组)
- 切片是数组的一个引用,因此切片是引用类型;
- 遍历切片、访问切片的元素、求切片的长度等操作与数组相同;
var array [5]int = [...]int{1,2,3,4,5}
slice := array[1:3]
fmt.Println(len(slice)) // 切片的长度,为2
fmt.Println(cap(slice)) // 切片的容量,不确定,动态变化的
切片声明和初始化
- 方式1:直接引用数组
var array [5]int = [...]int{1,2,3,4,5}
slice := array[1:3]
- 方式2:使用make创建
// make 也会创建一个数组,是由切片在底层进行维护,对外不可见
var slice []int = make([]int, 5, 10)
// 创建一个元素为int类型的切片,长度为5,容量为10
- 方式3:定义一个切片,直接就指定具体数组,使用原理类似make的方式
var slice []string = []string{"tom", "jack", "mary"}
切片的遍历
- 方式1:常规的for循环遍历
var arr [5]int = [...]int{10,20,30,40,50}
slice := arr[1:4]
for i := 0; i<len(slice); i++ {
fmt.Println(slice[i])
}
- 方式2:for range遍历
for i, v := range slice {
fmt.Println(i, v)
}
注意事项和细节
- 切片初始化时,不能越界,范围在[0 - len(array)]之间,但是可以动态增长;
- 切片声明完,但是未初始化时,需要用make后才能使用索引去添加,make是给切片分配空间:
slice = make([]int, 10)
,否则只能用append()
来添加; - 几种简写方式:
var slice = array[:endIndex]
var slice = array[startIndex:]
var slice = array[:]
- cap 是一个内置函数,用于统计切片的容量,即最大可以存放的元素数(可以动态变化);
- 切片定义完后,还不能使用,因为本身是一个空的,需要让其引用到一个数组或者make一个空间供切片来使用
- 切片可以继续切片
- append对数组进行追加操作:
- 切片append操作的本质,就是对数组的扩容;
- go底层会创建一个新的数组newArr(按照扩容后的大小)
- 将slice原来包含的元素拷贝到新的数组newArr;
- slice重新引用到newArr
- 注意,newArr是在底层来维护的,对外不可见
- 切片的拷贝操作
- copy(selice1, selice2) — 两个参数的数据类型是切片
- 参数的数据空间是独立的,互相不影响,即操作完毕以后,selice1改变,不影响selice2
- 如果selice2的长度大于selice1,不会报错,selice1拷贝selice2的前len(selice1)个元素
- 切片是引用类型,所以在传递时,遵循引用机制
var slice []int
var arr [5]int = [...]int {1,2,3,4,5}
slice = arr[:]
var slice2 = slice
slice2[0] = 10
//此时,selice,selice2,arr都变为[10,2,3,4,5]
string和切片
- string底层是一个byte数组,因此string也可以进行切片处理
- string是不可变的,所以可以用切片的方式获取,但是不能更改;
- 如果要修改字符串,需要 string —> []byte 或 []rune —> 修改 —> string(注:如果字符串中涉及到中文,就转换为[]rune类型)