切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。
切片是一个引用类型,它的内部结构包含地址
、长度
和容量
。切片一般用于快速地操作一块数据集合。
切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。
举个例子,现在有一个数组a := [8]int{0, 1, 2, 3, 4, 5, 6, 7}
,切片s1 := a[:5]
,相应示意图如下。
切片之间是不能比较的,我们不能使用==
操作符来判断两个切片是否含有全部相等元素。 切片唯一合法的比较操作是和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
来判断。
需要注意的是,切片扩容还会根据切片中元素的类型不同而做不同的处理,比如int
和string
类型的处理方式就不一样。
由于切片是引用类型,所以a和b其实都指向了同一块内存地址。修改b的同时a的值也会发生变化。
Go语言内建的copy()
函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()
函数的使用格式如下:
copy(destSlice, srcSlice []T)
其中:
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]
}
总结一下就是:要从切片a中删除索引为index
的元素,操作方法是a = append(a[:index], a[index+1:]...)
package main
import "fmt"
func main() {
var a = make([]string, 5, 10)
for i := 0; i < 10; i++ {
a = append(a, fmt.Sprintf("%v", i))
}
fmt.Println(a)
}