切片
切片(slice)是golang中一种特有的数据类型,切片是对数组一个连续片段的引用,所以切片是一个引用类型。这个片段可以是整个数组或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个相关数组的动态窗口。
数组有特定的用途,但是却有一些呆板(数组长度固定不可变),所以在Go语言的代码里并不是特别常见。相对的切片却是随处可见的,切片是一种建立在数组类型之上的抽象,它构建在数组之上并且提供更强大的能力和便捷。
# 创建切片
# 方式一
定义一个切片,然后让切片去引用一个已经创建好的数组。
// 定义一个数组
var intarr [6]int = [6]int{3, 6, 9, 1, 4, 7}
// 定义一个切片名字为slice
slice := intarr[1:3]
2
3
4
# 方式二
通过make内置函数来创建切片。
基本语法:
var 切片名 [type] = make([],len,[cap])
func main() {
// 定义切片:make 函数的三个参数:1.切片类型;2.切片长度;3.切片的容量
slice := make([]int, 4, 20)
fmt.Println(slice) // [0 0 0 0]
fmt.Println("切片的长度:", len(slice)) // 切片的长度: 4
fmt.Println("切片的容量:", cap(slice)) // 切片的容量: 20
slice[0] = 66
slice[1] = 88
fmt.Println(slice) // [66 88 0 0]
}
2
3
4
5
6
7
8
9
10
相关信息
make底层创建一个数组,对外不可见,所以不可以直接操作这个数组,要通过slice去间接的访问各个元素,不可以直接对数组进行维护/操作。
# 方式三
定义一个切片,直接就指定具体数组,使用原理类似Make的方式。
func main() {
slice := []int{1, 4, 7}
fmt.Println(slice) // [1 4 7]
fmt.Println("切片的长度:", len(slice)) // 切片的长度: 3
fmt.Println("切片的容量:", cap(slice)) // 切片的容量: 3
}
2
3
4
5
6
# 添加元素
func main() {
// 定义切片
var num []int
var num2 = []int{1, 2, 3, 4, 6}
// 添加一个元素
num = append(num, 1, 2, 3)
// 使用 ... 运算符添加多个元素到num中
num = append(num, num2...)
fmt.Println(num) // [1 2 3]
}
2
3
4
5
6
7
8
9
10
11
12
13
注意:需要对原切片重复赋值
# 切片拷贝
func main() {
// 定义切片
var a []int = []int{1, 4, 7, 3, 6, 9}
var b []int = make([]int, 10)
// 调用内置函数
copy(b, a)
fmt.Println(b) // [1 4 7 3 6 9 0 0 0 0]
}
2
3
4
5
6
7
8
9
# 删除元素
Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。
# 从开头位置删除
// 删除开头的元素可以直接移动数据指针
func main() {
// 定义切片
a := []int{1, 2, 3, 4, 5}
a = a[1:] // 从索引为 1 的位置开始截取包含 1
a = a[3:] // 从索引为 3 的位置开始截取包含 3
fmt.Println(a) // [5]
}
2
3
4
5
6
7
8
9
10
# 从中间位置删除
// 对于删除中间的元素,需要对剩余的元素进行一次整体挪动,同样可以用 append 或 copy 原地完成:
func main() {
// 定义切片
a := []int{1, 2, 3, 4, 5}
a = append(a[:1], a[1+1:]...) // 删除索引为 1 位置上的元素
fmt.Println(a) // [1 3 4 5]
}
2
3
4
5
6
7
8
# 从尾部删除
func main() {
// 定义切片
a := []int{1, 2, 3, 4, 5}
a = a[:len(a)-1] // 删除尾部1个元素
fmt.Println(a) // [1 2 3 4]
}
2
3
4
5
6
7
# 切片遍历
# for 循环
func main() {
slice := make([]int, 4, 20)
slice[0] = 66
slice[1] = 88
slice[2] = 99
slice[3] = 100
for i := 0; i < len(slice); i++ {
fmt.Println(slice[i])
}
}
2
3
4
5
6
7
8
9
10
11
12
# range 循环
func main() {
slice := make([]int, 4, 20)
slice[0] = 66
slice[1] = 88
slice[2] = 99
slice[3] = 100
for _, v := range slice {
fmt.Println(v)
}
}
2
3
4
5
6
7
8
9
10
11
12
# 小试牛刀
func main() {
// 定义一个数组
var intarr [6]int = [6]int{3, 6, 9, 1, 4, 7}
// 定义一个切片名字为slice
// [1:3]切片:切出的一段片段,索引从1开始,到3结束(不包含3)
slice := intarr[1:3]
// 输出数组
fmt.Println("intarr:", intarr) // intarr: [3 6 9 1 4 7]
// 输出切片
fmt.Println("slice", slice) // intarr: [3 6 9 1 4 7]
// 切片元素的个数
fmt.Println("slice的元素个数:", len(slice)) // intarr: [3 6 9 1 4 7]
// 获取切片的容量,容量可以动态变化
fmt.Println("slice的容量:", cap(slice)) // slice的容量: 5
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
相关信息
简写方式
var slice = arr[0:end] --> var slice = arr[:end]
var slice = arr[start:len(arr)] --> var slice = arr[start:]
var slice = arr[0:len(arr)] --> var slice = arr[:]
切片可以继续切片。
# 注意事项
切片定义后不可以直接使用,需要让其引用到一个数组或者make一个空间切片来使用。
切片使用不能越界。