Go语言入门到实战——06.Go语言里的数组和切片

Go语言入门到实战——00主目录
在上一讲中我们学习了Go语言的条件循环知识。

一.数组的声明

package typetest

import "testing"

func TestArray(t *testing.T) {
    
    
	var a [3]int //1.定义一个一维三元素的数组,未进行初始化值均为0
	b := [4]int{
    
    1, 2} //2.初始化一个数组,赋值b[0]=1,b[1]=2;但是b[2]及以后默认为0
	c := [2][2]int{
    
    {
    
    1, 2}, {
    
    3, 4}} //3.初始化定义多维数组
	d := [...]int{
    
    1, 2, 3, 4} //4.不知道具体多少个元素时可以打三个点
	t.Log(a, b, c, d)
}

在这里插入图片描述

二.数组的遍历

当然遍历数组的方式也需要说明一下:(一下两种方案等价)

package arrtest

import "testing"

func TestArray(t *testing.T) {
    
    
	var a = [...]int{
    
    1,2,3,4}
	for idx, e := range a {
    
    
		t.Log(idx, e)
	}
}
package arrtest

import "testing"

func TestArray(t *testing.T) {
    
    
	var a = [...]int{
    
    1, 2, 3, 4}
	for i := 0; i < len(a); i++ {
    
    
		t.Log(i, a[i])
	}
}

在这里插入图片描述
当然对于第一种写法我们需要考虑一个问题,就是当我们不需要idx时,我们可以这么写

//使用_进行占位,表示我们不关心idx,d但是下面的_不能写idx,因为这样后面不使用idx就会报错了
func TestArray(t *testing.T) {
    
    
	var a = [...]int{
    
    1,2,3,4}
	for _,e := range a {
    
    
		t.Log(e)
	}
}

三.切片

go语言的对数组进行切割可以得到切片的一般格式如下:

a[开始索引,结束索引) //注意是左闭右开

例子演示:

package arrtest

import "testing"

func TestArray(t *testing.T) {
    
    
	var a = [...]int{
    
    1, 2, 3, 4}
	t.Log(a[1:2])
	t.Log(a[1:len(a)])
	t.Log(a[:3])
	t.Log(a[2:])
}

在这里插入图片描述
这里请不要误以为是和python的切片一样了,比如下面的负数写法就不支持的

a[-1:],a[:-1]等等都不支持

这里我们需要注意的是数组和切片在go里面是不同的概念,数组的长度的容量都是不可变,而切片是可变的,关键是记住数组和切片可以看作是两种不同的'变量类型'
下面我们看一下类型的输出:

package arrtest
import (
	"reflect"
	"testing"
)

func TestArray(t *testing.T) {
    
    
	a := [...]int{
    
    1, 2, 3, 4}
	t.Log(len(a), cap(a))
	t.Log(reflect.TypeOf(a))
	t.Log(reflect.TypeOf(a[1:]))
}


从上面我们可以看到,数组类型是[4]int,而切片类型是[]int,需要仔细理解与区分
上面我们介绍了从数组获取切片的方法,接下来我们讲解一下切片本身的声明方案。

package typetest

import "testing"

func TestArray(t *testing.T) {
    
    
	//1.声明1,定义一个切片类型
	var s0 []int
	t.Log(len(s0), cap(s0)) //切片的长度和容量
	s0 = append(s0, 1)      //切片可以添加数据
	t.Log(len(s0), cap(s0)) //切片的长度和容量

	//2.声明2,定义一个空元素的切片类型
	s1 := []int{
    
    }
	t.Log(len(s1), cap(s1)) //切片的长度和容量

	//3.声明3,定义一个有初始元素的切片类型
	s2 := []int{
    
    1, 2, 3}
	t.Log(len(s2), cap(s2))

	//4.使用make构造切片,可以指定长度和容量
	s3 := make([]int, 3, 4)//长度为3,容量为4
	t.Log(len(s3), cap(s3))
	t.Log(s3[2])//初始化前三个元素为0,而第四个没有初始化是不可以访问的
	t.Log(s3[3])
}

在这里插入图片描述
接下来研究一下切片的容量增长的规律:

package typetest

import "testing"

func TestArray(t *testing.T) {
    
    
	var s []int = []int{
    
    }
	for i := 1; i <= 10; i++ {
    
    
		s = append(s, i) //必须接受返回值,否则相当于定义了一个新的变量但是未使用
						//底层的做法是会开辟新的连续存储空间,然后将原有的数据拷贝
						//到新的地址空间去,然后切片的初始地址也会发送变化,所以s需
						//要重新赋值
		t.Log(len(s), cap(s))
	}
}

在这里插入图片描述
从上面我们可以看出最开始插入第一个元素容量变为1了,而当往后面一个个插入时,超过容量便会乘以2.接下来我们需要知道的是切片的存储共享结构
在这里插入图片描述
两个切片共享了同一块区域,len的大小是可以直接知道的,那个cap容量的大小就是从起始位置到后面末端的长度,因为已经开辟了空间,可以接着放数据而不需要开辟新的空间.下面我们来验证一下:

package typetest

import "testing"

func TestArray(t *testing.T) {
    
    
	months := []string{
    
    "","Jan", "Feb", "Mar", "Apr", "May", "Jun", 
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
	slice1 := months[4:7]
	slice2 := months[6:9]
	t.Log(len(slice1), cap(slice1))
	t.Log(len(slice2), cap(slice2))
}

四.数组和切片的比较

//记住两点
1.数组是不可扩增容量的,而切片是可以的
2.数组可以进行比较,而切片是不可以的

上面两点留给读者去理解和测试

猜你喜欢

转载自blog.csdn.net/qq_44932835/article/details/121461636