数组是向来是编程语言中的一个很重要的数据结构之一。
在golang中数组是一个值类型。
先来看看golang中数组是怎么定义的
var arr [n]type //n为数组长度,type为数组的存储类型
再来看一下数组的声明方式
常规的声明方法:
var a [3]int //长度为3,每个元素为一个整型的数组
var b [3]*int //指向整型的指针数组
var c [3][3]int //二维数组,其中第一个中括号中数字可省略长度,后一个中括号中不可省略
//初始化操作
a = {1, 2, 3, 4, 5}
d = {{1, 2, 3},{4, 5, 6},{7, 8, 9}}
同样的,golang中也可以完成声明的同时完成初始化
a := [3]int{1, 2, 3} //声明并初始化一个长度为3的整型数组
b := [...]int{1, 2, 3} //省略数组长度使用...,让golang根据元素个数来计算长度
c := [3]int{1, 2} //定义一个长度为3的数组,对前两个元素进行赋值,其他元素为0
d := [...]int{8 : 2} //定义一个数组,将2赋值给该数组下标为8(第九个)的元素
e := [2][3]int{{1, 2, 3}, {4, 5, 6}}
上面完成了数组的声明和初始化,下面就来学习一下数组元素如何进行访问
通常使用数组的下标来进行数组内元素的访问
golang中有len()方法来对数组的长度进行计算
通过前面学习的for循环,可以达到遍历数组元素的目的.
a := [5]int{1, 2, 3, 4, 5}
for b := 0; b
输出结果:
var s1 []int
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
另一种访问方式为range访问
a := [5]int{1, 2, 3, 4, 5}
for i, v := range a {
fmt.Println(i, v)
}
输出结果同上
切片slice
切片的创建
var s1 []int //乍一看和数组创建没啥区别,但是切片在中括号中没有长度的明确数值或者使用...来表示
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s1 := a[9] //下标为9(第十个)元素
s2 := a[5: 9] //取下标5-8的元素 取首不取尾
s3 := a[ : 8] //取下标小于8的元素
s4 := a[3 : ] //起始下标为3之后的元素
s5 := a[ : ] //取数组里所有的元素
fmt.Println(a)
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
fmt.Println(s4)
fmt.Println(s5)
输出结果:
[1 2 3 4 5 6 7 8 9 10]
10
[6 7 8 9]
[1 2 3 4 5 6 7 8]
[4 5 6 7 8 9 10]
[1 2 3 4 5 6 7 8 9 10]
make声明slice
s1 := make([]int, 3, 5)
s2 := make([]int, 3)
fmt.Println(len(s1), cap(s1))
fmt.Println(len(s2), cap(s2))
输出结果:
3 5
3 3 //当容量不设定时,默认设置为当前切片长度为最大容量
我们来看一个slice切片的情况
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s1 := a[2 : 6]
s2 := s1[1 : 5]
fmt.Println(a)
fmt.Println(s1)
fmt.Println(s2)
输出结果:
[1 2 3 4 5 6 7 8 9 10]
[3 4 5 6]
[4 5 6 7]
为什么s1中切片只取到3,4,5,6,在s2中能取到s1中为取得的7呢?
我们不妨输出一下s1的容量cap(s1)得到的是8,也就是说切片s1中取得的容量为[2 : ]的长度,在reslice时,索引被slice的切片为准,同时索引不可以超过被slice的切片容量,如果索引越界,就会引发错误
改变slice切片中的值
a := []int{1, 2, 3, 4, 5, 6}
s1 := a[1 : 4] //1 2 3
s2 := a[2 : 5] //2 3 4
fmt.Println(s1, s2)
s2[0] = 0
fmt.Println(s1, s2)
结果输出
[2 3 4] [3 4 5]
[2 0 4] [0 4 5]
我们发现当改变切片s2中的下标为0的值(对应a数组中下标为2)时,切片s1下标为1(对应a数组中下标为2)的值也相对发生了改变,这样就很好的展现了,slice指向的是一个底层的数组,当多个slice指向同一个底层数组时,其中一个slice的值发生改变,另一个相同数组下标的元素也发生改变,同样的,当slice切片因为容量不足,重新创建一个slice后改变其元素时,共享的对应数组元素不发生改变,因为扩展后的slice切片地址发生了改变.
append追加切片元素
s1 := make([]int, 2, 8)
fmt.Printf("%v %p\n", s1)
s1 = append(s1, 1, 2, 3, 4)
fmt.Printf("%v %p\n", s1, s1)
s1 = append(s1, 5, 6, 7, 8)
fmt.Printf("%v %p\n", s1, s1)
输出结果:
[0 0] 0xc04206e040
[0 0 1 2 3 4] 0xc04206e040
[0 0 1 2 3 4 5 6 7 8] 0xc042070080
可以看到,当添加元素在切片容量范围内,地址不变化,返回原始的slice,当添加元素超过切片容量范围,拷贝原始的slice到新的地址中,增加容量,在追加元素
copy函数
s1 := []int{1, 2, 3, 4}
s2 := []int{1, 2, 3, 4}
s3 := []int{1, 2, 3, 4}
s4 := []int{1, 2, 3, 4}
s5 := []int{5,6}
s6 := []int{5,6}
s7 := []int{5,6}
copy(s1,s5)
fmt.Println(s1)
copy(s5,s2)
fmt.Println(s5)
copy(s6, s3[0 : 2])
fmt.Println(s6)
copy(s4[1 : 2], s7[0 : 1])
fmt.Println(s4)
输出结果:
[5 6 3 4]
[1 2]
[1 2]
[1 5 3 4]