持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
一、为什么需要切片:
先看一个需求:我们需要一个数组用于保存学生的成绩,但是学生的个数是不确定的,请问怎么办?
解决方案:使用切片
二、切片的基本介绍:
- 切片的英文是
Slice - 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。
- 切片的使用和数组类型,遍历切片、访问切片的元素和求切片长度
len(slice)都一样。 - 切片的长度是可以变化的,因此切片是一个可以动态变化数组。
- 切片定义的基本语法:
var 变量名 []类型
比如:var a []int
package main
import "fmt"
func main() {
// 演示切片的基本使用:
var intArr [5]int = [...]int{1, 22, 33, 66, 99}
// 声明/定义一个切片
// 1. slice 就是切片
// 2. intArr[1:3] 表示 slice 引用到 intArr 这个数组的第二个元素到下标元素为3 但是不包含3
// 简称:顾头不顾腚
slice := intArr[1:3]
fmt.Println("intArr = ", intArr)
fmt.Println("slice 的元素是 = ", slice)
fmt.Println("slice 的元素个数 = ", len(slice))
fmt.Println("slice 的容量 = ", cap(slice)) // 切片的容易是可以动态变化的
}
三、切片在内存中形式
为了让大家更加深入的理解切片,我们画图分析一下切片在内存中是如何布局的,这个是一个非常重要的知识点(以前面的案例来分析 - 画出前面的切片布局)
切片:就是把数组分隔成一片一片的
切片还可以继续指向其它数组或数值,因为切片存的只是它们的地址
package main
import "fmt"
func main() {
// 演示切片的基本使用:
var intArr [5]int = [...]int{1, 22, 33, 66, 99}
// 声明/定义一个切片
// 1. slice 就是切片
// 2. intArr[1:3] 表示 slice 引用到 intArr 这个数组的第二个元素到下标元素为3 但是不包含3
// 简称:顾头不顾腚
slice := intArr[1:3]
fmt.Println("intArr = ", intArr)
fmt.Println("slice 的元素是 = ", slice)
fmt.Println("slice 的元素个数 = ", len(slice))
fmt.Println("slice 的容量 = ", cap(slice)) // 切片的容易是可以动态变化的
fmt.Printf("intArr[1]的地址 = %p\n", &intArr[1])
fmt.Printf("sclic[0]的地址 = %p\n", &slice[0])
}
对上述代码的总结:
从上面可以看到:
- slice 的确是一个引用类型。
- slice 从底层来说,就是一个数据结构(struct 结构体)
type slice struct {
ptr *[2]int
len int
cap int
}
- 以前面的案例来分析切片在内存中的布局。
- 切片底层的数据结果可以理解成是一个结构体
struct - 输出切片和切片引用的地址。