数组
由固定长度的特定类型元素组成的序列,一个数组可由零或多个元素组成。默认情况下,数组的每个元素都被初始化为元素类型对应的零值。
初始化
var a = [3]int{1,2,3}
// 省略号表示数组的长度根据初始化值的个数来计算
var b = [...]int{1,2,3}
var c = [2]int{1,2}
a == c // compile error
数组长度是数组类型的一个组成部分,因此 [3]int 和 [2]int 是两个不同的类型。数组的长度必须是常量表达式,因为数组的长度需要在编译阶段确定。
如果数组的元素类型是可以相互比较的,那么数组类型也是可以相互比较的
参数传递
func reverse1(a [3]int) {
a[0], a[2] = a[2], a[0]
}
func reverse2(a *[3]int) {
a[0], a[2] = a[2], a[0]
}
func main() {
a := [3]int{1,2,3}
reverse1(a)
fmt.Println(a) // [1 2 3]
reverse2(&a)
fmt.Println(a) // [3 2 1]
}
从中可以看出,数组是一个值类型,将数组作为参数直接传递给函数只会复制数组的一个副本,这一点和 C 不同。
由于数组长度固定,是一个僵化类型,所以在Go语言中我们很少使用数组,更多的是用切片
Slice
Slice 代表变长的序列,序列中每个元素都有相同的类型。slice 是一个轻量级的数据结构,底层引用一个数组对象,一个 slice 由三个部分构成:指针、长度和容量。指针指向第一个 slice 元素对应底层数组的地址,长度对应 slice 元素的数目,容量一般是从 slice 开始位置到底层数据的结尾位置。
初始化
var array = [5]int{1,2,3,4,5}
var a = array[:]
var b = []int{1,2,3}
var c = []int(nil) // c == nil, true
// 容量可省略,默认等于长度
var d = make([]int, 5)[:]
var e = make([]int, 5, 10)
slice 不可比较,唯一合法的是和 nil 比较,注意就算 slice 的长度和容量都为空,slice 也不一定为 nil,如var s = []int{}
append
用于向切片的末尾追加元素,当容量不足时,Go会采用一定的策略自动扩容,可以同时添加多个元素或切片
var s []int
s = append(s, 1, 2, 3)
var q []int
q = append(q, s...)
新的切片可能还会引用原来的底层数组,也可能会引用一个新创建的底层数组,取决于Go的内存策略