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

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

相关推荐
混迹网络的权某5 分钟前
每天一道C语言精选编程题之求数字的每⼀位之和
c语言·开发语言·考研·算法·改行学it·1024程序员节
IronmanJay3 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组
加载中loading...4 小时前
Linux线程安全(二)条件变量实现线程同步
linux·运维·服务器·c语言·1024程序员节
Wx120不知道取啥名4 小时前
C语言之长整型有符号数与短整型有符号数转换
c语言·开发语言·单片机·mcu·算法·1024程序员节
biomooc5 小时前
R语言 | paletteer包:拥有2100多个调色板!
r语言·数据可视化·1024程序员节
Hello.Reader5 小时前
FFmpeg 深度教程音视频处理的终极工具
ffmpeg·1024程序员节
Y.O.U..6 小时前
STL学习-容器适配器
开发语言·c++·学习·stl·1024程序员节
就爱敲代码6 小时前
怎么理解ES6 Proxy
1024程序员节
憧憬一下6 小时前
input子系统的框架和重要数据结构详解
arm开发·嵌入式·c/c++·1024程序员节·linux驱动开发
三日看尽长安花6 小时前
【Tableau】
1024程序员节