go中的切片(Slice)相对于其它语言来说是一个特色
切片,顾名思义,切的是数组,成就的是数组中的一个片段
切片是一个具有相同元素的一个可自然增长的序列。非常灵活,可支持扩容
切片是一个引用类型,内部结构包含地址,长度和容量,可以快速的操作一块数据集合
举个例子,有一个数组a := [8]int{0, 1, 2, 3, 4, 5, ,6, 7},切片s1 := a[:5]
切片s1 := a[:5],因为数组地址是从0开始,相当于对于切片的解读,左闭右开,左包含,右不包含
切片s2 := a[3:6],示意图如下
切片表达式
完整的切片表达式
a[low : hign : max]
high的上限边界是切片的容量cap(a),切片的索引必须满足0 <= low <= hign <= len(a)
func main() {
a := [5]int{1, 2, 3, 4, 5}
s := a[1:3] // s := a[low:high]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
s2 := s[3:4] // 索引的上限是cap(s)而不是len(s)
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
}
切片之间不能直接比较,不能用 == 操作符判断两个切片是否含有全部相等元素,切片唯一合法的比较操作时和nil比较。
一个nil
值的切片并没有底层数组,一个nil
值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil
,
例如下面的示例
var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
所以如果想要判断一个切片是否为空,只能用len(s) == 0来判断,不能用s == nil判断
index,value是切片的两个元素
即遍历这个切片可以使用遍历索引
func main() {
s := []int{1, 3, 5}
for i := 0; i < len(s); i++ {
fmt.Println(i, s[i])
}
for index, value := range s {
fmt.Println(index, value)
}
}
当然,for索引也是可以的
切片扩容
append()可以为切片动态的添加元素
func main(){
var s []int
s = append(s, 1) // [1]
s = append(s, 2, 3, 4) // [1 2 3 4]
s2 := []int{5, 6, 7}
s = append(s, s2...) // [1 2 3 4 5 6 7]
}
可以将一个切片后面添加上元素,也可以为一个切片后面添加上一个切片。
当然,切片的扩容也是通过append()
func main() {
//append()添加元素和切片扩容
var numSlice []int
for i := 0; i < 10; i++ {
numSlice = append(numSlice, i)
fmt.Printf("%v len:%d cap:%d ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
}
}
append()函数就像一个胶带把切片中的各个元素串联起来,专心为切片结构服务
修改元素的值需要首先知道该元素的地址,切片结构就是引用类型,即凭着接片上的index就可以得到所储存的元素,直接修改值即可
func main() {
a := []int{1, 2, 3, 4, 5}
b := a
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(b) //[1 2 3 4 5]
b[0] = 1000
fmt.Println(a) //[1000 2 3 4 5]
fmt.Println(b) //[1000 2 3 4 5]
}
copy()切片的使用格式为:
copy(destSlice, srcSlice []T)
func main() {
// copy()复制切片
a := []int{1, 2, 3, 4, 5}
c := make([]int, 5, 5)
copy(c, a) //使用copy()函数将切片a中的元素复制到切片c
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
c[0] = 1000
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1000 2 3 4 5]
切片是引用类型,可以直接对值进行修改,Go语言中,一般前面为主,后面是对该元素的定的类型,可延展为在copy(a,c)中,a是主,将c的值赋给a
切片中删除元素比较难,Go语言中没有专门的函数来删除切片中的元素,所以只能根绝切片的特性来删除元素
func main() {
// 从切片中删除元素
a := []int{30, 31, 32, 33, 34, 35, 36, 37}
// 要删除索引为2的元素
a = append(a[:2], a[3:]...)
fmt.Println(a) //[30 31 33 34 35 36 37]
}
可以理解为,把切片分成段,然后用append()函数,将除了要删除的元素的下标,其它的元素串联起来其格式为
删除索引为index的元素:
a = append(a[:index],a[index+1]...)
左包含,右不包含