数组

Go的数组和其它语言基本上一样,是长度固定的特定类型元素组成的序列,这基本上是所有语言数组的特性。和其它语言相比差异主要在声明和初始化的写法上,下面是简单声明一个数组:

var a [5]int
fmt.Println(a[0])
fmt.Println(fmt.Println(a[len(a)-1]))

上面的a是一个长度为5的整数数组,如果没有给定初始值它里面的元素默认值是0Go数组的下标是从0开始的,len函数返回数组中元素的个数。我们可以在声明数组的时候初始化它的值:

var m [3]int = [3]int{1, 2, 3}
var n [3]int = [3]int{2, 3}

这里的mn都是长度为3的数组,m对应的值是1, 2, 3而由于n初始化的时候只有2个值,因此它里面的值是2, 3, 0
如果采用简单声明:=的方式声明一个数组,可以指定数组的大小,也可以不指定大小这时它会根据初始化值的个数来确定:

a := [10]int{} //元素都为0
b := [...]int{1, 2} //长度为2

Go 也可以直接指定一个索引和值,来初始化,如果声明的时候长度不指定,那最大的索引加1就是数组的长度:

a := [10]int{1:2} // 长度10,a[1] = 2 其它为0
b := [...]int{1:2, 10:1} //长度11,a[1] = 2 a[10] = 1其它为0

数组a长度声明是10,只给了索引1的值为2,其余都为0。数组b声明的时候索引12101,它的长度是11

修改数组中某个索引的值方式和其它语言一样:

a := [10]int{}
a[0] = 10

数组的类型是由元素的类型和长度共同决定的,[3]int[4]int是两种不同的数组类型。因此:

a := [3]int{1, 2, 3}
a = [4]int{1, 2, 3, 4}

编译的时候会报错,而:

a := [3]int{1, 2, 3}
a = [3]int{4, 5, 6}

是正确的

Slice

上面说的数组长度是固定,使用的时候不是很灵活,slice的长度是可变,简单声明一个未初始化的slice

var a []int
print(len(a))
print(cap(a))

slice也可以利用len返回它的长度,刚才声明的slice长度为0。除了长度slice还有一个容量cap的概念,用cap可以返回它的容量。长度不能超过它的容量。slice的声明也可以用make,用make声明可以指定容量和可以不指定容量,这时容量和长度一致:

a := make([]int, 10) //长度为10,容量为10
a := make([]int, 10, 12) //长度为10 容量为12

slice可以进行切片操作slice[i:j],创建一个新的slice,新的slice范围是原来slice下标ij-1,也可以不指定下标slice[:j]则是默认从0j-1,同理如果slice[i:]就是从i到最后一个元素,下面是一个简单的例子:

a := []int {1, 2, 3, 4, 5}
b = a[1:2]
c = a[:2]
d = a[1:]

需要注意的是切片操作slice[i:j]j可以大于slice的长度,只要它小于容量

刚才一直讲到容量,那它到底有什么实际意义呢?开始slice的时候说过它长度是可变的,哪怎么改变了?通过append就可以对slice追加元素,这时容量就有作用了,如果append的时候当前长度小于容量,那slice不会扩大容量,也不会申请新的空间,而是在原来的基础上把长度加1就行了,如果容量等于长度,则会扩容,扩容会申请新的空间。

package main

func main() {
	a := make([]int, 10, 11)
	a = append(a, 1)
	println(len(a), cap(a)) // 11 11

	a = append(a, 1)
	println(len(a), cap(a)) // 12 12
}
07-17 09:49