Go:slice使用

文章目录

数组

基本认识

数组元素可以通过 索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推(数组以 0 开始在所有类 C 语言中是相似的)。元素的数目(也称为长度或者数组大小)必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2GB

在内存中,数组中的元素默认会初始化为0

基本使用

下面先看如何进行遍历

go 复制代码
func test1() {
	var arr1 [5]int
	for i := 0; i < len(arr1); i++ {
		fmt.Println(i, arr1[i])
	}
}

另外一种遍历方式是使用range进行遍历,具体如下

go 复制代码
func test2() {
	var arr1 [5]int
	for i, j := range arr1 {
		fmt.Println(i, j)
	}
}

这也是一种遍历的方式,其中i表示的是下标,而j表示的是下标对应数组的值,这点和之前的逻辑是一样的

new创建数组

在Go中,数组的创建是可以使用new来进行创建的,原因在于Go中的数组是一种值类型,而不是像C++中是一个指向首元素地址的指针,参考如下两种创建方式

go 复制代码
var arr1 = new ([5]int)
var arr2 [5]int

这两种操作的区别就在于,当把一个数组赋值给另外一个的时候,需要再做一次数组的拷贝操作,将内存进行一个拷贝,比如

go 复制代码
arr2 := *arr1
arr2[2] = 100

这样的话,两个数组就都有了不同的值,之后对于arr2的修改操作是不会影响到arr1的

数组传参

对于数组传参来说,其实说的就是上面的这个逻辑

当函数中,数组作为参数进行传入的时候,就会进行一次数组内存的拷贝操作,函数内部的修改是不会影响函数内部的修改的,如果想要进行修改,需要使用&来进行传递,具体的实现如下所示

go 复制代码
func t4func1(arr [5]int) {
	fmt.Println("t4fun1before", arr)
	for i := 0; i < len(arr); i++ {
		arr[i] += 3
	}
	fmt.Println("t4func1after", arr)
}

func t4func2(arr *[5]int) {
	fmt.Println("t4fun2before", arr)
	for i := 0; i < len(arr); i++ {
		arr[i] += 3
	}
	fmt.Println("t4func2after", arr)
}

func test4() {
	var arr1 [5]int
	t4func1(arr1)
	fmt.Println(arr1)

	t4func2(&arr1)
	fmt.Println(arr1)
}

输出结果为

text 复制代码
t4fun1before [0 0 0 0 0]
t4func1after [3 3 3 3 3]
[0 0 0 0 0]
t4fun2before &[0 0 0 0 0]
t4func2after &[3 3 3 3 3]
[3 3 3 3 3]

由此可见,这里是和C++有一点相似的,但是也有一点不同,如果传递指针的话也可以直接进行使用,实际上可以理解为传递的是一种引用

数组常量

如果提前知道了数组的值,那么在创建的时候是可以提前进行初始化的,这点和之前的逻辑一样,不过在写法上有一些创新:

go 复制代码
func test5() {
	arr1 := [5]int{1, 2, 3}
	arr2 := [5]int{3: 2, 4: 2}

	fmt.Println(arr1)
	fmt.Println(arr2)
}

新增了可以在初始化的时候就指定数组下标对应的元素是什么

数组的传参

数组的传参有较高的成本,于是有两种方式可以避免传参的时候带来的拷贝问题

  1. 传递数组的指针
  2. 传递数组的切片

使用数组的指针来进行操作实际上前面已经演示过了,而在实际的场景中其实也不会使用数组的指针来进行操作,更多使用的是切片,所以直接看切片

slice切片

定义

切片 (slice) 是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在切片内。切片提供了一个相关数组的动态窗口

切片定义后,默认为nil,长度为0

下面演示利用数组生成切片的几种定义方式

go 复制代码
func test6() {
	arr1 := [6]int{0, 1, 2, 3, 4, 5}

	// 生成的切片是arr1中,下标[2, 4)对应的内容,也就是2 3
	s1 := arr1[2:4]
	fmt.Println(s1)

	// 还可以这样生成,下标[3, 6)对应的内容,也就是3 4 5
	s2 := arr1[3:]
	fmt.Println(s2)

	// 还可以这样生成,下标[0, 4)对应的内容,也就是0 1 2 3
	s3 := arr1[:4]
	fmt.Println(s3)

}

传参

在通常进行参数传递的时候,其实会将参数声明为一个切片,当调用函数的时候,就把数组进行分片,然后把切片引用进行传递给函数即可

go 复制代码
func sum(a []int) int {
	res := 0
	for _, v := range a {
		res += v
	}
	return res
}

func test8_func(a []int) {
	for i, _ := range a {
		a[i] = 0
	}
}

func test8() {
	a := [5]int{1, 2, 3, 4, 5}
	fmt.Println(sum(a[:]))
	fmt.Println(sum(a[1:]))

	test8_func(a[3:])
	fmt.Println(a)
}

make分配内存

对于切片来说,想要进行实际的分配还有其他的方式,不一定一定要借助

相关推荐
希忘auto13 小时前
详解Redis的常用命令
redis·1024程序员节
yaosheng_VALVE1 天前
探究全金属硬密封蝶阀的奥秘-耀圣控制
运维·eclipse·自动化·pyqt·1024程序员节
dami_king1 天前
SSH特性|组成|SSH是什么?
运维·ssh·1024程序员节
一个通信老学姐6 天前
专业125+总分400+南京理工大学818考研经验南理工电子信息与通信工程,真题,大纲,参考书。
考研·信息与通信·信号处理·1024程序员节
sheng12345678rui6 天前
mfc140.dll文件缺失的修复方法分享,全面分析mfc140.dll的几种解决方法
游戏·电脑·dll文件·dll修复工具·1024程序员节
huipeng9267 天前
第十章 类和对象(二)
java·开发语言·学习·1024程序员节
earthzhang20217 天前
《深入浅出HTTPS》读书笔记(19):密钥
开发语言·网络协议·算法·https·1024程序员节
爱吃生蚝的于勒8 天前
计算机基础 原码反码补码问题
经验分享·笔记·计算机网络·其他·1024程序员节
earthzhang20218 天前
《深入浅出HTTPS》读书笔记(20):口令和PEB算法
开发语言·网络协议·算法·https·1024程序员节
一个通信老学姐8 天前
专业140+总分410+浙江大学842信号系统与数字电路考研经验浙大电子信息与通信工程,真题,大纲,参考书。
考研·信息与通信·信号处理·1024程序员节