学习golang(5) 初探:go 数组/slice 的基本使用

简介: 学习golang(5) 初探:go 数组/slice 的基本使用

你可能很好奇,为啥 学习golang(3) 初探 过了 ,直接就来到了 学习golang(5) 初探,因为运维小学生不想提“4”字眼,以免犯忌讳,导致服务器无辜宕机。



数组


数组基本使用

数组作为go基本的类型之一,我们来看下,和其他语言数组一样,需要先固定数组长度,且申请,然后再使用,我们来看下具体的用法。


数组申请


例如,我们可以看如下申请数组的例子

其中1,2 比较常见,不过多追诉,我们看看第三种,

申请语句 c := [...]int{1, 2, 3, 4, 5}

当数组长度定义为...,那么该数组的长度是由数据元素决定的

注意,数组长度应当是常量,数组c应当在编译时,就确定下来了的,本质上,该值还是常量。

image.png


我们尝试下运行


image.png


数组类型查看,并进行比较


我们可以使用 reflect.TypeOf是可以看到变量的类型的

go对于数组类型来看,[3]int[2]int是同的数据类型,所以在编译的时候,会抛错,无法进行比较

我们尝试下,我们修改脚本

image.png


我们尝试运行下

image.png


这里可以看到,go数组abc类型是[5]int

所以才能比较,我们再申请一个长度不一样的呢

image.png

我们尝试下运行

image.png

我们发现,报错了,原因是类型不一致



函数调用

和其他语言一样,数组函数调用,若不传入地址,则传入的是形参,形参修改不会影响到元数据

若想修改元数据,则需要传入指针

若我们传入形参,并且函数中进行修改


image.png


我们运行查看下数据是否改变

image.png


上述例子中,就是我们传入的是形参,相当于是数据的拷贝,当函数执行完毕后,函数中的数组a则被销毁了,元数据没有影响的


如何修改元数据呢?


我们有2种方法

  • return函数数组a
  • 使用指针将a传入函数中

方法1: 将函数数组return出来


我们再改变后,我们将数组的信息给返回给主函数,主函数适应数组接收

image.png

我们运行看看

image.png


方法2:我们传入指针

image.png

执行

image.png



slice


什么是slice


数组在go中是使用的比较少的,使用最多的还是slice,但是看slice还是需要数组的相关知识才行。


你可以将slice是一个可变长的“数组”,且它有三个属性构成: 起始地址、长度 和 容量。


我们使用make可以声明slice

例如,我们有如下语句: a := make([]int,0,10) 则为分配一个底层数组为10,有效长度为0,且容量为10的切片,映射为数据结构,大概是这样的

image.png

其中,array指向底层数组的起始地址、len为有效长度,这里为0,cap为容量,这里为10

当我们直接操作该slice的时候,会出错,例如

我们尝试下

image.png

可以看到,报错为越界了

image.png


我们使用append新增一个数据

语句 a = append(a,9)

此时,映射为数据结构,大概是这样的


image.png

我们此时再访问,a[0]则是没有问题的,我们尝试下

image.png

执行

image.png


若当lencap相等后,此时若又要append数据,此时会开辟新空间

例如:

假设当前slice数据结构如下

image.png



若此时,还需要append追加元素,则

会申请一个新的数组,且将老数组数据拷贝到新数组中

image.png


又将cap修改为最新大小,且将起始地址,指向新数组,并且将老数组销毁

image.png


然后执行追加即可,这基本上就是slice变化过程(简化过的)



slice的基本使用


如何查看起始地址、长度和容量


如我们前面所述,每一个slice有起始地址、长度和容量,那么我们如何查看其值呢?

我们可以使用cap()来查询容量,使用len()来查询长度,使用%p查看地址

我们创建一个slice容量为3,长度为2,且一直append追加5个元素,我们看下

程序如下

image.png


我们执行一下

image.png

我们可以发现,当容量为 3 、6、12时候,我们起始地址都是新的,这也验证了我们之前所述的扩容逻辑



slice和数组搭配使用

slice不仅可以创建底层数组,而且还可以直接对数组进行切片,例如

image.png


对于sliceb 而言,b[0]== a[1],且b[0]就是a[1]引用,即: 修改了b[0]的值,就等同于修改了a[1]的值

如上面所述,我们slice不是有3个属性么,即: 起始地址、长度 以及 容量,那么对于slice b它的数据结构大致为


image.png


我们尝试下

代码如下

image.png


我们执行查看下结果

image.png


可见,和我们猜想的无意,接下来的append追加和上述又一致了,且len == cap后再进行追加,又会新开辟数组了。


我们来模拟尝试下

我们创建数组a[2],且创建sliceb = a[0:2],然后追加3个数据,再次修改b[0]的元素,我们查看下a[0]是否更改


我们代码编写如下

image.png



我们执行下看结果

image.png

可见,如果slice引用了新的底层数组,老数组的信息是不会变动了的。




总结


其实在goslice使用的比数组要广,slice 它有三个属性,分别是 起始地址,长度以及容量,当容量不够了的时候,go会进行扩容,扩容的基本思想就是创建一个新的数组,然后将老数组的数据拷贝至新数组中,然后销毁老数组,且容量为新数组的长度,然后再进行扩容即可。


这就是数组 和 slice的基本使用咯。






























相关文章
|
3月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
109 1
|
4月前
|
Go 索引
Go语言数组的定义与操作 - 《Go语言实战指南》
本文介绍了 Go 语言中的数组(Array)相关知识,包括定义、初始化方式(默认、显式、指定索引及自动推导长度)、访问与修改、遍历方法(for 循环和 for range)、值类型特性(复制行为)、多维数组支持以及其与切片的区别。数组是定长且同类型的集合,适合性能敏感场景,但实际开发中更常用动态的切片(slice)。
123 11
|
9月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
167 7
|
4月前
|
人工智能 Go
[go]Slice 切片原理
本文详细介绍了Go语言中的切片(slice)数据结构,包括其定义、创建方式、扩容机制及常见操作。切片是一种动态数组,依托底层数组实现,具有灵活的扩容和传递特性。文章解析了切片的内部结构(包含指向底层数组的指针、长度和容量),并探讨了通过`make`创建切片、基于数组生成切片以及切片扩容的规则。此外,还分析了`append`函数的工作原理及其可能引发的扩容问题,以及切片拷贝时需要注意的细节。最后,通过典型面试题深入讲解了切片在函数间传递时的行为特点,帮助读者更好地理解和使用Go语言中的切片。
|
6月前
|
Go 开发者
go-carbon v2.6.0 重大版本更新,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持
108 3
|
9月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
184 67
|
10月前
|
JSON Go 开发者
go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。
205 4
|
10月前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
233 6
|
10月前
|
Unix Linux Go
go进阶编程:Golang中的文件与文件夹操作指南
本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
167 4
|
12月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
396 4
Golang语言之管道channel快速入门篇

推荐镜像

更多