我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go 切片

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go 切片

切片

一、切片(slice)概念
在讲解切片(slice)之前,大家思考一下数组有什么问题?

  1. 数组定义完,长度是固定的。例如:
var num [5]int = [5]int{1,2,3,4,5}

定义的num数组长度是5,表示只能存储5个整型数字,现在向数组num中追加一个数字,这时会出错。因为你已经定义死了。

  1. 使用数组作为函数参数进行传递时,如果实参为5个元素的整型数组,那么形参也必须5个元素的整型数组,否则出错。

针对以上两个问题,可以使用切片来进行解决。

切片与数组的区别: 切片与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大,所以可以将切片理解成“动态数组”,但是,它不是数组。

二、 切片与数组区别
通过定义,来比较一下切片与数组的区别。

  1. 先回顾数组的基本定义初始化:a := [5]int{},数组中[]是一个固定的数字,表示长度。定义完后,长度是固定,最多存储5个数字。
  2. 切片的基本定义初始化如下:s:=[]int{}//定义空切片看定义的方式,发现与数组很相似.但是注意:切片中的[]是空的,或者是“…”。切片的长度和容量可以不固定。现在通过程序演示,动态向切片中追加数据
/ 初始化切片s := []int{1,2,3}// 通过append函数向切片中追加数据s = append(s,5,6,7)fmt.Println(s)

append()函数,第一个参数表示向哪个切片追加数据,后面表示具体追加的数据。最终输出结果为

[1 2 3 5 6 7]

三、 切片其它定义方式

  1. 定义空切片:
//声明切片和声明数组一样,只是少了长度,此为空(nil)切片var s1 []int 
  1. 通过make()函数实现
//借助make函数, 格式 make\(切片类型, 长度, 容量\)s := make([]int, 5, 10)

四、切片的长度与容量

长度是已经初始化的空间(以上切片s初始空间默认值都是0)。容量是已经开辟的空间,包括已经初始化的空间和空闲的空间。我们可以通过如下图来理解切片的长度与容量:
在这里插入图片描述
该切片的长度是5(存有数据,注意如果没有赋值,默认值都是0),容量是10,只不过有5个空闲区域。即使没有给切片s赋值,初始化的空间(长度)默认存储的数据都是0。

s := make([]int,5,8)fmt.Println(s)

输出的结果是:

[0 0 0 0 0]

在使用make()函数定义切片时,一定要注意,切片长度要小于容量,例如:

// 以下是错误的s := make([]int, 10, 5)

make()函数中的容量参数是可以省略掉的,如:

s := make([]int,10)

这时长度与容量是相等的,都是10.
GO语言提供了相应的函数来计算切片的长度与容量,示例如下:

s := make([]int,5,10)fmt.Println("长度是",len(s))fmt.Println("容量是",cap(s))

接下来给切片s赋值,可以通过下标的方式直接来进行赋值。如下所示:

s := make([]int,5,10)s[0] = 1s[1] = 2

也可以通过循环的方式来进行赋值。

s := make([]int,5,10)for i:=0;i<len(s) ;i++ {  s[i] = i}

在这里一定要注意,循环结束条件是小于切片的长度,而不是容量。因为,切片的长度是指的是初始化的空间。以下方式会出现异常错误

for i:=0;i<cap(s) ;i++ {  s[i] = i}

给切片赋完值后,怎样将切片中的数据打印出来呢?

  1. 第一种方式:直接通过下标的方式输出,例如:s[0],s[1]…。
  2. 第二种方式: 通过循环的方式,注意循环结束的条件,也是小于切片的长度,如下所示:
for i:=0;i<len(s) ;i++ {  fmt.Println(s[i])}

或者使用range方式输出:

for _,v := range s {  fmt.Println(v)}

四、 切片截取
首先说一下切片的截取操作,所谓截取就是从切片中获取指定的数据。
我们通过如下程序给大家解释一下:

//定义切片 并且完成初始化s := []int{10,20,30,0,0}//从切片s中截取数据slice := s[0:3:5]fmt.Println(slice)

以上程序输出结果:

[10 20 30]

其中s[0:3:5]是什么意思呢?我们来解释一下。每个位置的数字为s[low:high:max]:

  1. 第一个数low表示下标的起点(从该位置开始截取),如果low取值为0表示从第一个元素开始截取,也就是对应的切片s中的10。
  2. 第二个数high表示取到哪结束,也就是下标的终点(不包含该位置),3表示取出下标是0,1,2的数据(10,20,30),不包括下标为3的数据,那么也就是说取出的数据长度是3。可以根据公式:3-0计算(len=high-low),也就是第二个数减去第一个数,差就是数据长度。在这里可以将长度理解成取出的数据的个数。
  3. 第三个数用来计算容量,所谓容量:是指切片目前可容纳的最多元素个数。通过公式5-0计算(cap=max-low),也就是第三个数据减去第一个数。该案例中容量为5。

现在将以上程序进行修改:

//定义切片 并且完成初始化s := []int{10,20,30,40,50}//从切片s中截取数据slice := s[0:3:5]fmt.Println(slice)

结果是:

[10 20 30]

因为起点还是0,也就是10开始,终点还是3也就是到30结束.长度是3,容量是5。

继续修改该程序:

//定义切片 并且完成初始化s := []int{10,20,30,40,50}//从切片s中截取数据slice := s[0:4:5]fmt.Println(slice)

结果是:

[10 20 30 40]

因为起点还是0,也就是10开始,终点还是4也就是到40结束。长度是4,容量是5。
继续修改该程序

//定义切片 并且完成初始化s := []int{10,20,30,40,50}//从切片s中截取数据slice := s[1:4:5]fmt.Println(slice)

slice切片结果是:

[20 30 40]

那么容量是多少呢?容量为4,通过第三个数减去第一个数(5-1)计算。

通过画图的方式来表示slice切片中的容量。
在这里插入图片描述
通过上面的图,可以发现切片s经过截取操作以后,将结果赋值给切片slice后,长度是3,容量是4,只不过有一块区域是空闲的。

切片其他操作。

如下表所示:
在这里插入图片描述
下面通过一个案例,演示一下。

  1. s[:]:
    在这里插入图片描述
    结果是所有的值。

s[low:]
在这里插入图片描述
结果是下标3后面的所有值。

  1. s[:high]
    在这里插入图片描述
  2. s[low:high]
    在这里插入图片描述
    结果是2-5的值。array[2:5]表示从下标为2的元素(包含该元素)开始取,到下标为5的元素(不包含该元素)结束。所以切片s5的长度是3。切片s5的容量是多少呢?是8,根据array切片的容量是10,减去array[2:5]中的2。

以上就是关于切片的基本操作,这些操作在以后的开发过程中会经常用到,希望大家记住基本的规律。

五、 思考题

接下来说,思考如下题,定义一个切片array,然后对该切片array进行截取操作(范围自定义),得到新的切片s6,并修改切片s6某个元素的值。代码如下:
在这里插入图片描述
s6切片的结果是:[2,3,4]因为是从下标为2的元素(包含)开始取,到下标为5的元素(不包含)结束,取出3个元素,也就是长度为3。

现在将程序进行如下修改:
在这里插入图片描述
现在程序的输出结果是:

s6 = [2 3 888]

因为切除了234,然后现在0是2,1是3,2是4,然后把s6[2]也就是s6[4]赋值为888
接下来输出切片array的值:
在这里插入图片描述
输出的结果如下:

s6 = [2 3 888]array = [0 1 2 3 888 5 6 7 8 9]

发现切片array中的值也发生了变化,也就是修改切片s6的值会影响到原切片array的值,下面通过画图的形式来说明其原因。
在这里插入图片描述
在这里重点要理解的是:s6 := array[2:5],将array切片中的array[2],array[3],array[4]截取作为新切片s6,实际上是切片s6指向了原切片array(在这里并不是为切片s6新建一块区域)。所以修改s6,也会影响到array。

下面继续修改上面的程序:
在这里插入图片描述
以上程序中,切片s7的值是多少?

结果是:s7 = [888 5 6 7 8]

下面也是通过画图的形式,来解释该程序的结果:
在这里插入图片描述
继续思考,现在在原有的程序中又加了一行,如下图所示:
在这里插入图片描述
最终,切片s7与原来切片array的值分别是多少?

结果所示:

s6 = [2 3 888]s7 = [888 5 999 7 8]array = [0 1 2 3 888 5 999 7 8 9]

六、 append函数的使用

在第一节中,已经给大家讲解过切片与数组很大的一个区别就是:切片的长度是不固定的,可以向已经定义的切片中追加数据。并且也给大家简单的演示过通过append的函数,在原切片的末尾添加元素。

arr := []int{1,2,3}arr = append(arr,4) //追加一个数arr = append(arr,5,6,7) //追加多个数fmt.Println(arr)

如果容量不够用了,该怎么办呢?

例如有以下切片:

s:= make([]int, 5, 8)

定义了切片s,长度是5,容量是8,k。

s := make([]int,5,8)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))

结果是:len = 5 cap = 8

并且前面我们讲解过,长度是指已经初始化的空间,现在切片s没有赋值,但是默认值为0
验证如下所示:

s := make([]int,5,8)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))fmt.Println(s)

结果是:

len = 5 cap = 8[0 0 0 0 0]

现在开始通过append函数追加数据,如下所示:

s := make([]int,5,8)s = append(s,1)fmt.Println(s)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))

输出结果是:

[0 0 0 0 0 1]len = 6 cap = 8

从输出的结果上,我们完全能够体会到,append函数的作用是在末尾追加(直接在默认值后面追加数据),由于追加了一个元素,所以长度为6.

但是如果我们把程序修改成如下所示:

s := make([]int,5,8)//s = append(s,1)s[0] = 1fmt.Println(s)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))

输出结果是:

[1 0 0 0 0]len = 5 cap = 8

由于s[0]=1是直接给下标为0的元素赋值,并不是追加,所以结果的长度不变。

下面我们继续通过append( )继续追加数据:

s := make([]int,5,8)s = append(s,1)s = append(s,2)s = append(s,3)fmt.Println(s)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))

结果是:

[0 0 0 0 0 1 2 3]len = 8 cap = 8

追加完成3个数据后,长度变为了8,与容量相同。

那么如果现在通过append( )函数,继续向切片s中继续追加一个数据,那么容量会变为多少呢?

代码如下:

s := make([]int,5,8)s = append(s,1)s = append(s,2)s = append(s,3)s = append(s,4)fmt.Println(s)fmt.Printf("len = %d,cap=%d\n",len(s),cap(s))

输出的结果是:

[0 0 0 0 0 1 2 3 4]len = 9 cap = 16

追加完成一个数据后,长度变为9,大于创建切片s时的容量,所以切片s扩容,变为16.

那么切片的容量是否是以2倍容量来进行扩容的呢?

我们可以来验证一下:
在这里插入图片描述
输出结果是:
在这里插入图片描述
通过以上结果分析,发现是2倍的容量进行扩容。

但是我们修改一下循环条件看一下结果,将循环结束的条件修改的大一些,如下所示:
在这里插入图片描述
对应的结果:
在这里插入图片描述
通过以上的运行结果分析:当容量小于1024时是按照2倍容量扩容,当大于等于1024就不是按照2倍容量扩容。

七、 copy函数使用

针对切片操作常用的方法除了append()方法以外,还有copy方法。

基本语法:copy(切片1,切片2)

将第二个切片里面的元素,拷贝到第一个切片中。

下面通过一个案例,看一下该方法的使用:
在这里插入图片描述
上面案例中,将class="lazy" data-srcSlice中的元素拷贝到destSlice切片中。结果如下:

dst = [1 2 6 6 6]

通过以上结果可以分析出,直接将class="lazy" data-srcSlice切片中两个元素拷贝到dstSlice元素中相同的位置。而dstSlice原有的元素备替换掉。

下面将以上程序修改一下,如下所示:
在这里插入图片描述
以上程序的结果是:

class="lazy" data-src = [6 6]

通过以上两个程序得出如下结论:在进行拷贝时,拷贝的长度为两个slice中长度较小的长度值。

思考以下程序输出的结果:
在这里插入图片描述
结果是:

slice2 = [1 2 3]

现在将程序进行如下修改:
在这里插入图片描述
结果是:

slice1 = [5 4 3 4 5]

八、切片作为函数参数

切片也可以作为函数参数,那么与数组作为函数参数有什么区别呢?

接下来通过一个案例,演示一下切片作为函数参数。
在这里插入图片描述
通过以上案例,发现在主函数main()中,定义了一个切片s,然后调用InitData()函数,将切片s作为实参传递到该函数中,并在InitData()函数中完成初始化,该函数并没有返回值,但是在主函数中直接打印切片s,发现能够输出对应的值。也就是在InitData()函数中对形参切片num赋值,影响到了main()函数中的切片s。

但是,大家仔细想一下,如果我们这里传递参数不是切片,而是数组,那么能否完成该操作呢?

那么我们将上面的程序,修改成以数组作为参数进行传递的形式:
在这里插入图片描述
发现以数组的形式作为参数,并不能完成我们的要求,所以切片作为函数实参与数组作为函数实参,进行传递时,传递的方式是不一样的。

在GO语言中,数组作为参数进行传递是值传递,而切片作为参数进行传递是引用传递。

九、值传递和引用传递:

  • 值传递:方法调用时,实参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参数的值
  • 引用传递:也称为传地址。函数调用时,实际参数的引用(地址,而不是参数的值)被传递给函数中相对应的形式参数(实参与形参指向了同一块存储区域),在函数执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。

建议:以后开发中使用切片来代替数组。

来源地址:https://blog.csdn.net/weixin_47906106/article/details/132406073

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Go 切片

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Go 切片

切片 一、切片(slice)概念 在讲解切片(slice)之前,大家思考一下数组有什么问题? 数组定义完,长度是固定的。例如: var num [5]int = [5]int{1,2,3,4,5} 定义的num数组长度是5,表示只能存储5个
2023-08-30

切片与Go中的切片

问题内容在go中的unsafe.SliceData函数的文档中,它说:SliceData returns a pointer to the underlying array of the argumentslice.If cap(sli
切片与Go中的切片
2024-02-06

Go(3[切片])

切片:切片底层都是数组切片是一个指针类型,是数组的引用!修改切片后的值,那原来的数据也会改变传输数据大的时候,使用切片,节省内存,因为底层只是对数组的引用append操作的适合,如果长度超过设置的长度,那底层就会把底层元组进行扩容切片里面可
2023-01-31

Go 语言中 nil 切片、非 nil 切片、空切片

php小编小新为你带来了关于Go语言中的切片类型的介绍。在Go语言中,切片有三种状态:nil切片、非nil切片和空切片。这三种切片状态在使用时具有不同的含义和特点。了解这些切片类型的区别,将有助于我们更好地理解和使用Go语言中的切片功能。接
Go 语言中 nil 切片、非 nil 切片、空切片
2024-02-08

在go中重新切片2d切片

一分耕耘,一分收获!既然打开了这篇文章《在go中重新切片2d切片》,就坚持看下去吧!文中内容包含等等知识点...希望你能在阅读本文后,能真真实实学到知识或者帮你解决心中的疑惑,也欢迎大佬或者新人朋友们多留言评论,多给建议!谢谢!问题内容我遇
在go中重新切片2d切片
2024-04-05

Go 切片的用法

问题内容我正在查看 sha1 相关代码 https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/crypto/sha1/sha1.go;l=146-152 尤其是这一行 a
Go 切片的用法
2024-02-05

Go中的nil切片和空切片区别详解

Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil
2022-06-07

go语言切片是什么

go语言切片是对数组的一种抽象。切片是对数组的引用,包含了指向数组元素的指针、切片的长度和容量。创建切片的方式有:1、使用内置的make函数创建一个切片;2、使用切片的字面量创建一个切片;3、从另一个切片创建新的切片。可以使用内置的appe
go语言切片是什么
2023-12-11

Go切片slice实例分析

本文小编为大家详细介绍“Go切片slice实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go切片slice实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。slice表示切片(分片),例如对一个数组
2023-06-30

Go slice切片如何使用

这篇文章主要介绍“Go slice切片如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Go slice切片如何使用”文章能帮助大家解决问题。定义切片区别于数组,是引用类型, 不是值类型。数组是
2023-07-02

Go 中的切片类型转换

php小编苹果为大家介绍Go语言中的切片类型转换。在Go语言中,切片是一种动态数组,常用于存储和操作一组相同类型的元素。切片类型转换是指将一个类型的切片转换为另一个类型的切片,这在实际开发中非常常见。本文将详细介绍切片类型转换的注意事项和实
Go 中的切片类型转换
2024-02-10

go语言切片怎么生成

本篇内容介绍了“go语言切片怎么生成”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在go语言中,切片(slice)是对数组的一个连续片段的引
2023-07-04

Go - 将指向结构切片的指针转换为接口切片

php小编百草在Go编程语言中,有时候我们需要将指向结构切片的指针转换为接口切片。这种转换在一些特定的情况下非常有用,例如当我们需要对一个切片中的元素进行修改时。通过将指针转换为接口切片,我们可以方便地访问和修改切片中的元素,而无需担心数据
Go - 将指向结构切片的指针转换为接口切片
2024-02-09

Go语言copy()实现切片复制

本文主要介绍了Go语言copy()实现切片复制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-14

go的切片扩容机制详解

本文主要介绍了go的切片扩容机制详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-14

聊聊go语言中的切片(slice)

本篇文章带大家了解一下golang中可变长度的"数组"——切片(slice),希望对大家有所帮助!golang切片(slice)(1)切片的定义切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一个引用类型,它的内部结构包含地址、长度和容量。切片一般用于快速地操作一块数据集合。【相关推荐:Go视频教程】创建切片跟创建数组唯一的区别
2022-07-04

Go数组与切片轻松掌握

在Java的核心库中,集合框架可谓鼎鼎大名:Array、List、Set等等,随便拎一个出来都值得开发者好好学习如何使用甚至是背后的设计源码。虽然Go语言没有如此丰富的容器类型,但也有一些基本的容器供开发者使用,接下来让我们认识一下这些容器类型吧
2022-11-21

Go语言切片支持多维吗

这篇文章主要介绍“Go语言切片支持多维吗”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Go语言切片支持多维吗”文章能帮助大家解决问题。可以。Go语言的切片是支持多维的,声明一个多维切片的语法格式“v
2023-07-05

编程热搜

目录