字数:1467, leoay 技术圈
你好, 我是 leoay, 又好几天不见了,今天我想聊一下 Golang 中切片和数组的区别。
说到数组,我们应该都不陌生吧,因为基本上每种编程语言中有它的身影;而切片呢?也是一种数据结构,python中也有切片的概念。
数组和切片都可以用来存储一组数据。
但是不同的是数组的长度是固定的,而切片则是可变的;切片就类似于一个可变的数组。
其实,在Go语言中数组和切片外表看起来很像,也因此有时候我们很容易搞混淆,下面我就用几个例子对比一下数组和切片的差异。
数组
因为数组是固定长度的,所以在定义数组时,我们必须指定数组的长度
代码语言:javascript复制var array1 [3] int //长度为3的整型数组,默认值是3个0
arr := [5]int{1, 2, 3, 4, 5} //长度为5的数组,并赋值
var array2 = [...]int{6, 7, 8} //不声明长度,长度取总元素个数3
array3 := [...] int {1,2,3} //不声明长度的数组,长度取总元素个数3
array4 := [...] int {99:-1} //长度为100的数组,只有最后一个是-1,其他都是0(大括号中前面一个是最大下标,后面则是对应的值)
和其他语言的数组一样, Golang 的数组也是通过下标访问元素的。
slice
slice,即切片,表示一个拥有相同类型元素的可变长度序列。
slice通常被写为[]T,其中元素的类型都是T;它看上去就像没有长度的数组类型。
数组和slice其实是紧密关联的,它们可以很方便地相互转换。
slice可以看成是一种轻量级的数据结构,可以用来访问数组的部分或者全部元素,而这个数组称之为slice的底层数组。
但是slice和数组是不同的,slice有三个属性:指针,长度和容量,而数组就没有容量这个属性。
其中,指针指向底层数组的第一个可以从slice中访问的元素,这个元素不一定是数组的第一个元素。
长度指的是slice中的元素个数,不能超过slice的容量。
容量的大小通常大于等于长度,会随着元素个数增多而动态变化。Go语言的内置函数len 和 cap 用来返回slice的长度和容量。
下面看一下怎么定义slice:
代码语言:javascript复制sllice1 := []int{1, 2, 3} //注意与数组初始化的区别,在内存中构建一个包括有3个元素的数组,然后将这个数组的应用赋值给s这个Slice
array1 := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0} //a是数组
slice2 := array1[2:8] //从数组中切片构建Slice
slice3 := make([]int, 10, 20) //make函数初始化,len=10,cap=20
从上面的例子中我们可以看出,数组和slice还是很像,我们可以通过数组构建slice,也可以直接用make创建空的slice,至于make的用法,其实在 Go 中有好几种,后面 涉及到 channel 的文章时再细说。
关于 slice 的扩容
我们已经知道了 slice 的长度不是固定,所以它支持扩容。
在 Go 中我们也用 append 函数来为 slice 扩容。但是这儿有个疑问,如果我们在定义 slice 时已经指定好了长度和容量, 那么扩容时会有什么影响呢?
一般来说,如果我们在对 slice 追加元素时, 容量不够了, 那么其容量一般按照原来的2倍进行扩容, 而长度呢,则会更新为实际的元素个数,可以通过下面这部分代码看效果:
代码语言:javascript复制package main
import "fmt"
func print_info(my_slice []int) {
fmt.Println("len :",len(my_slice))
fmt.Println("cap :",cap(my_slice))
for i,v :=range my_slice{
fmt.Println("element[",i,"]=",v)
}
fmt.Printf("%p", my_slice)
}
func main() {
slice1 := make([]int,5,6)
print_info(slice1)
slice2 := append(slice1,8,9,10)
print_info(slice02)
}
其实,进一步观察上面的代码,当我们把扩充前后的 slice 的地址打印出来后发现,它们是不一样的,这就说明扩充并不只是简简单单地在原来的 slice 后面追加元素,而是新创建了一个 slice。
实际上新的 slice 中的前面的元素是从原来的slice中拷贝过来的。
好了,今天的这篇文章就写到这里了,怎么样?看完以后是不是觉得对 Go 中数组和 slice 的认识又多了亿点点,如果觉得文章写得 ok,请给个点赞,以后我会花更多时间陪你在技术的海洋中遨游!