文章目录
为什么需要切片
需求:当我们需要用一个数组保存学生的成绩,但是学生的个数是不确定的,我们可以使用切片。
切片的基本介绍
- 切片的英文是
slice
- 切片是数组的一个引用,因此切片是引用类型,在进行传递时,须遵守引用传递的机制
- 切片的使用和数组类似,遍历、访问元素、求长度
len(slice)
都和数组一样 - 切片的长度是可以变化的,因此切片是一个可以动态变化的数组
- 切片定义的基本语法:
var 切片名 []类型
比如:var a []int
快速入门
package main
import "fmt"
func main() {
var arr = [...]int{
11, 22, 33, 44, 55, 66, 77}
var slice = arr[2:6] // 数组arr的[2, 6)下标的元素值
fmt.Printf("arr的值 = %v\tarr的类型 = %T\n", arr, arr)
fmt.Printf("slice的值 = %v\t\tslice的类型 = %T\n", slice, slice)
fmt.Printf("slice的长度 = %v\n", len(slice))
// 底层数组的长度:7 - 2 = 5(arr的长度7减去[2:6]左边的2)
fmt.Printf("slice的容量 = %v\n", cap(slice))
}
/*结果:
arr的值 = [11 22 33 44 55 66 77] arr的类型 = [7]int
slice的值 = [33 44 55 66] slice的类型 = []int
slice的长度 = 4
slice的容量 = 5
*/
切片在内存中的布局
示意代码:
package main
import "fmt"
func main() {
var arr = [...]int{
11, 22, 33, 44, 55, 66, 77}
// slice从【arr下标为2的元素】开始引用
var slice = arr[2:6]
fmt.Println("arr[2]的地址 =", &arr[2])
fmt.Println("slice[0]的地址 =", &slice[0])
fmt.Println(&arr[2] == &slice[0])
fmt.Println("修改前slice =", slice)
// 修改slice[1]的值
slice[1] = 100
fmt.Println("修改后slice =", slice)
// 这时arr[3]也发生了改变
fmt.Println("修改后arr =", arr)
}
/*结果:
arr[2]的地址 = 0xc00000a250
slice[0]的地址 = 0xc00000a250
true
修改前slice = [33 44 55 66]
修改后slice = [33 100 55 66]
修改后arr = [11 22 33 100 55 66 77]
*/
上述代码的内存示意图:
初始化切片
- 方式1:定义一个切片,然后让切片去引用一个已经创建好的数组,前面的案例已经演示过了
- 方式2:内建函数make分配并初始化一个类型为切片的对象
package main
import "fmt"
func main() {
// 容量必须>=其长度
var sl = make([]int, 7, 10)
for i := range sl {
sl[i] = (i + 1) * 11
}
fmt.Printf("sl的值 = %v\n", sl)
fmt.Printf("sl的类型 = %T\n", sl)
fmt.Printf("sl的长度 = %v\n", len(sl))
fmt.Printf(