数组和切片有何异同?
Go 语言中的切片(slice)结构体的本质是对数组的封装,描述一个数组的片段。无论是数组还是切片,都可以通过下标来访问单个元素。
数组是定长的,长度定义好之后,不能修改。在Go 语言中,数组是不常见的,因为其长度是类型的一部分,限制了它的表达能力,比如[3]int 和 [4]int 就是不同的类型。而切片则是非常灵活的,它可以动态地扩容,而且切片的类型和长度无关。
看一个栗子:
func main() {
arr1 := [1]int{1}
arr2 := [2]int{1, 2}
if arr1 == arr2 {
fmt.Println("相同的类型")
}
}
尝试运行,会报编译错误:
invalid operation: arr1 == arr2 (mismatched types [1]int and [2]int)
因为两个数组的长度不同,根本不是同一个类型,所以不能进行比较。
数组是一片连续的内存,切片实际上是一个结构体,包含三个字段: 长度,容量,底层数组。
// src/runtime/slice.go
type slice struct {
array unsafe.Pointer
len int
cap int
}
切片的数据结构如下图所示:
需要注意的是,底层数组可以被多个切片同时指向,因此对一个切片的元素进行操作时有可能会影响到其他切片。