1. 切片的本质
在go语言当中,切片(slice)是使用最为频繁的数据结构之一,其原因在于它在处理同类型数据序列有着方便且高效的特点,所以今天我就来和大家聊聊我对切片的理解!
1.1 数组
首先,谈到切片,肯定是不能避开数组的,因为切片是在数组之上的抽象数据类型。数组由长度和类型两部分组成,如[3]int类型表示由 3 个 int 整型组成的数组。数组以索引方式进行访问,例如表达式 s[n] 访问数组的第 n 个元素。数组的长度是固定的,长度是数组类型的一部分。长度不同的 2 个数组是不可以相互赋值的,因为这 2 个数组属于不同的类型。例如下面的代码是不合法的:
a := [3]int{1, 2, 3}
b := [4]int{2, 4, 5, 6}
a = b // cannot use b (type [4]int) as type [3]int in assignment
其次,在go语言当中,数组变量是属于值类型,当一个数组类型变量进行赋值或者值传递时,实际上会复制整个数组。如下面代码所示,当把a赋值给b,此时修改b中的元素并不会改变b的元素。
a := [...]int{1, 2, 3} // ... 会自动计算数组长度
b := a
a[0] = 100
fmt.Println(a, b) // [100 2 3] [1 2 3]
为了避免复制数组,一般会传递指向数组的指针
func modify(p *[5]int) {
(*p)[0] = 666
fmt.Println("modify *a = ", *p)
}
func main() {
a := [5]int{1, 2, 3, 4, 5}
modify(&a)
fmt.Println("main: a = ", a)
}
1.2 切片
由于数组长度固定,缺少灵活性,所以通常都使用相比数组功能更强大,使用更便利的切片来处理处理同类型数据序列。
(1)切片的初始化
var a = []int{1,2,3,4,5} //切片使用字面量初始化类似于数组,但不需要指定长度
或
var a = make([]int, len, cap)
//1.第一个参数是 []T,T 即元素类型,
//2.第二个参数是长度 len,即初始化的切片拥有多少个元素