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分配内存

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

相关推荐
学传打活2 天前
【边打字.边学昆仑正义文化】_进阶篇5 宇宙星系的运转(续1)
微信公众平台·1024程序员节·汉字·昆仑正义文化
fangzhanpeng16810 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心12 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552718 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552719 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝20 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552720 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552721 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552723 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552723 天前
Java I/O核心操作实战
人工智能·1024程序员节