文章目录
- 数组
- Slice
数组
Go
的数组和其它语言基本上一样,是长度固定的特定类型元素组成的序列,这基本上是所有语言数组的特性。和其它语言相比差异主要在声明和初始化的写法上,下面是简单声明一个数组:
var a [5]intfmt.Println(a[0])fmt.Println(fmt.Println(a[len(a)-1]))
上面的
a
是一个长度为
5
的整数数组,如果没有给定初始值它里面的元素默认值是
0
。
Go
数组的下标是从0开始的,
len
函数返回数组中元素的个数。我们可以在声明数组的时候初始化它的值:
var m [3]int = [3]int{1, 2, 3}var n [3]int = [3]int{2, 3}
这里的
m
和
n
都是长度为
3
的数组,
m
对应的值是
1, 2, 3
而由于
n
初始化的时候只有
2
个值,因此它里面的值是
2, 3, 0
。
如果采用简单声明
:=
的方式声明一个数组,可以指定数组的大小,也可以不指定大小这时它会根据初始化值的个数来确定:
a := [10]int{} //元素都为0b := [...]int{1, 2} //长度为2
Go
也可以直接指定一个索引和值,来初始化,如果声明的时候长度不指定,那最大的索引加
1
就是数组的长度:
a := [10]int{1:2} // 长度10,a[1] = 2 其它为0b := [...]int{1:2, 10:1} //长度11,a[1] = 2 a[10] = 1其它为0
数组
a
长度声明是
10
,只给了索引
1
的值为
2
,其余都为
0
。数组
b
声明的时候索引
1
为
2
,
10
为
1
,它的长度是
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 []intprint(len(a))print(cap(a))
slice
也可以利用
len
返回它的长度,刚才声明的
slice
长度为
0
。除了长度
slice
还有一个容量
cap
的概念,用
cap
可以返回它的容量。长度不能超过它的容量。slice的声明也可以用
make
,用
make
声明可以指定容量和可以不指定容量,这时容量和长度一致:
a := make([]int, 10) //长度为10,容量为10a := make([]int, 10, 12) //长度为10 容量为12
slice
可以进行切片操作
slice[i:j]
,创建一个新的
slice
,新的
slice
范围是原来
slice
下标
i
到
j-1
,也可以不指定下标
slice[:j]
则是默认从
0
到
j-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 mainfunc main() {a := make([]int, 10, 11)a = append(a, 1)println(len(a), cap(a)) // 11 11a = append(a, 1)println(len(a), cap(a)) // 12 12}