golang语言学习#5-数组

数组是向来是编程语言中的一个很重要的数据结构之一。

在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]


由此可以看到,当短的slice拷贝到长的slice中,slice对应的长度不变,内容拷贝至对应位置,当长的slice拷贝到短的slice中,长度也不变,只拷贝长度内的元素.同样的,copy支持指定下标拷贝元素

你可能感兴趣的:(golang语言学习#5-数组)