切片(slice)
引子
因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性。 例如:
func arraySum(x [3]int) int{
sum := 0
for _, v := range x{
sum = sum + v
}
return sum
}
这个求和函数只能接受[3]int
类型,其他的都不支持。 再比如,
a := [3]int{
1, 2, 3}
数组a中已经有三个元素了,我们不能再继续往数组a中添加新元素了。
切片的定义
切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。
切片是一个引用类型,它的内部结构包含地址
、长度
和容量
。切片一般用于快速地操作一块数据集合。
声明切片类型的基本语法如下:
var name []T
其中,
- name:表示变量名
- T:表示切片中的元素类型
举个例子:
func slice_1() {
// 切片的定义
var s1 []int // 声明一个字符串切片
var s2 []string // 声明一个整型切片
fmt.Println(s1, s2) // [] []
fmt.Println(s1 == nil) // true
fmt.Println(s1 == nil) // true
// 初始化
s1 = []int{
1, 2, 3}
s2 = []string{
"Hello", "World", "你好", "世界"}
fmt.Println(s1, s2) // [1 2 3] [Hello World 你好 世界]
fmt.Println(s1 == nil) // false
fmt.Println(s1 == nil) // false
// 定义的同时初始化
var s3 = []int{
4, 5, 6}
fmt.Println(s3) // [4 5 6]
}
切片的长度和容量
切片拥有自己的长度和容量,我们可以通过使用内置的len()
函数求长度,使用内置的cap()
函数求切片的容量。
切片的容量是指底层数组从第一个元素到最后的容量
func slice_1() {
var s1 []int{
1, 2, 3, 1000}
var s2 []string{
"Hello", "World", "你好", "世界"}
// 切片的长度和容量
fmt.Printf("%d的长度为:%d, %d的容量为:%d\n",s1, len(s1), s1, cap(s1))
fmt.Printf("%s的长度为:%d, %s的容量为:%d",s2, len(s2), s2, cap(s2))
}
--->>>
[1 2 3 1000]的长度为:4, [1 2 3 1000]的容量为:4
[Hello World 你好 世界]的长度为:4, [Hello World 你好 世界]的容量为:4
由数组得到一个切片
func slice_2() {
// 由数组得到一个切片
a1 := [...]int{
1,3,5,7,9,11,13,15}
s3 := a1[0:5] // 基于一个数组切割得到切片(左闭右开)
fmt.Printf("%T,%T\n", a1, s3)
fmt.Printf("s3为:%d",s3)
}
--->>>
[8]int,[]int
s3为:[1 3 5 7 9]
为了方便起见,可以省略切片表达式中的任何索引。省略了low
则默认为0;省略了high
则默认为切片操作数的长度:
func slice_2() {
// 由数组得到一个切片
a1 := [...]int{
1,3,5,7,9,11,13,15}
s4 := a1[3:] // 等同于a1[3:len(a1)]
s5 := a1[:3] // 等同于a1[0:3]
s6 := a1[:] // 等同于a1[0:len(a1)]
fmt.Println("\ns4:",s4,"\ns5:",s5,"\ns6:",s6)
}
--->>>
s4: [7 9 11 13 15]
s5: [1 3 5]
s6: