概述
切片Slice代表变长的序列。语法和数组很想,只是没有固定长度而已。
而且实际开发中,基本使用slice代替数组来使用,主要原因是数组是值传递。
slice有三部分组成:指针、长度、容量。
slice的底层引用了一个数组对象,纸质恩只想第一个slice元素对应的底层数组元素的地址。
内置函数len()返回slice的长度,cap()返回slice的容量。
多个slice可以引用同一个底层数据。
使用
声明时默认cap和len相同,除非特殊指定
- 字面量声明
//此时slice1的len和cap都是5
var slice1=[]int{1,2,3,4,5}
- make函数声明
make函数创建一个匿名的数组变量,然后返回一个slice,cap可以省略,cap省略将和len相等。
make([]T,len,cap)
//此时slice1的len和cap都是5
var slice1=make([]int,10)
var slice1=make([]int,10,20)
-
append函数
s2=append(s1,a)
append接受变长参数,支持添加多个元素:s2=append(s1,s0...)
append时,如果长度超过cap,那么会重新分配一个大的内存,然后将cap翻倍,再将原数据拷贝进去返回新的内存地址。 -
其他
使用时的注意事项
-
slice不要引用大数组的一小部分,因为只要地址上的数据被引用,那么这个数据就不会被释放。
当这个大数组不再被使用时,此时它应该被回收,但是因为slice对其中一小部分引用的原因导致这个大数组没有被回收,从而导致很大的资源浪费。此时应该将引用的部分复制出来。copy(a,b)
把b拷贝给a。 -
数组可以做
==
比较,但是切片不可用。安全的做法是禁止slice之间作比较,slice唯一合法的比较是和nil比较。 -
一个nil值得slice没有底层数组,len和cap都是0;字面量初始化的slice不是nil值。所以判断一个slice是否为空应该用
len(s)==0
判断,而不是使用nil值判断。
package main
import (
"fmt"
)
func main() {
var sli1 []int
var sli2 []int=[]int{}
fmt.Println(sli1==nil,"=>",len(sli1),"=>",cap(sli1))//true => 0 => 0
fmt.Println(sli2==nil,"=>",len(sli2),"=>",cap(sli2))//false => 0 => 0
}
- 其他