数组的声明
var a [3]int // 声明初始化为默认零 值
a[0] = 1
b := [3]int{1, 2, 3} // 声明同时初始化
c := [2][2]int{{1, 2}, {3, 4}} // 多维数组初始化
测试实例 1
func TestArrayInit(t *testing.T) {
var arr[3]int
arr1 := [4]int{1,2,3,4}
arr2 := [...]int{1,2,3}
t.Log(arr[0], arr[1], arr[2])
t.Log(arr1[1])
t.Log(arr2[1])
}
数组元素遍历
与其他主要编程语言的差异
通过代码实例了解一下
测试实例 2
// 数组遍历
func TestArrayTravel(t *testing.T) {
arr := [...]int{1,2,3}
for i:= 0; i < len(arr); i++ {
t.Log(arr[i])
}
// Go 语言写法,类似于 java 中的 for each 写法
for idx, e := range arr {
t.Log(idx, e)
}
// 如果不关心 idx,那么将对应位置置为 _
for _, e := range arr {
t.Log(e)
}
}
数组截取
a[开始索引(包含),结束索引(不包含)]
func TestTruncatedArray(t *testing.T) {
a := [...]int{1, 2, 3, 4, 5}
t.Log(a[1:2]) // [2]
t.Log(a[1:3]) // [2 3]
t.Log(a[1:len(a)]) // [2 3 4 5]
t.Log(a[1:]) // [2 3 4 5]
t.Log(a[:3]) // [1 2 3]
}
切片内部结构
切片内部结构是一个结构体
ptr
指针,指向一个连续存储空间len
元素的个数,可以访问的元素的个数cap
内部数组的容量
通过代码实例 3 感受一下 len
与 cap
的区别
package slice_test
import "testing"
func TestSliceInit(t *testing.T) {
// 声明一个 slice,并不需要指定数组的长度
var s0 []int
t.Log(len(s0), cap(s0)) // 0 0
s0 = append(s0, 1)
t.Log(len(s0), cap(s0)) // 1 1
s1 := []int{1, 2, 3, 4}
t.Log(len(s1), cap(s1)) // 4 4
s2:=make([]int, 3, 5)
t.Log(len(s2), cap(s2))
t.Log(s2[0], s2[1], s2[2]) // 0 0 0
//t.Log(s2[3], s2[4]) // panic: runtime error: index out of range [3] with length 3
s2 = append(s2, 9)
t.Log(len(s2), cap(s2)) // 4 5
t.Log(s2[3]) // 9
}
切片共享存储结构
在介绍这之前,我们先来了解一下 cap
的增长过程,参见实例代码 3
测试实例 3
func TestSliceGrowing(t *testing.T) {
s := []int{}
for i := 0; i < 10; i++ {
s = append(s, i)
t.Log(len(s), cap(s))
}
}
运行结果
从代码的运行结果可以看出:cap
会在放入的元素个数已经超出原有的 cap
容量时,cap
的值会增长,并且每一次 cap
的增长都是前一次的 2 倍。不过每一次增长,slice 都会开辟一个新的连续内存空间,并将原有的值复制过去。
接下来,我们介绍 slice 的共享存储结构
测试实例 4
func TestSliceShareMemory(t *testing.T) {
months := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
Q2 := months[3:6]
t.Log(Q2) // [Apr May Jun]
t.Log(len(Q2), cap(Q2)) // 3 9
summer := months[5:8]
t.Log(summer) // [Jun Jul Aug]
t.Log(len(summer), cap(summer)) // 3 7
// 共享数组的修改会影响到所有人
summer[0] = "Unknown"
t.Log(Q2) // [Apr May Unknown]
}
数组 vs. 切片
- 容量是否可伸缩
- 是否可以进行比较
测试实例 5
func TestSliceCompare(t *testing.T) {
a := []int{1, 2, 3, 4}
b := []int{1, 2, 3, 4}
// invalid operation: a == b (slice can only be compared to nil)
if a == b {
t.Log("equal")
}
}
代码实例 5 说明:slice 是不可以比较的,或者说只可以和 nil
进行比较