- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Go 切片只需这一篇!由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
大家好,我是盼盼.
切片在 golang 是一种很重要的数据结构,大家平时工作和面试都会遇到,而且切片需要注意的点比较多,只有深入去理解它,才能避免采坑。下面开始发车.
数组 。
数组是内置类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.
在初始化后长度是固定的,无法修改其长度。当作为方法的参数传入时将复制一份数组而不是引用同一指针.
数组的长度也是其类型的一部分,通过内置函数len(array)获取其长度.
还有几点要注意的:
切片 。
Go中提供了一种灵活,功能强悍的内置类型Slices切片(“动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大.
切片中有两个概念:一是len长度,二是cap容量,长度是指已经被赋过值的最大下标+1,可通过内置函数len()获得.
容量是指切片目前可容纳的最多元素个数,可通过内置函数cap()获得。切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象.
不过要注意的是,在容量不足的情况下,append的操作会导致重新分配内存,可能导致巨大的内存分配和复制数据代价.
a = append([]int{0}, a...) 切片头部添加元素。在开头一般都会导致内存的重新分配,而且会导致已有的元素全部复制1次.
因此,从切片的开头添加元素的性能一般要比从尾部追加元素的性能差很多.
切片的内部实现 。
切片是一个很小的对象,它对底层的数组(内部是通过数组保存数据的)进行了抽象,并提供相关的操作方法.
切片是一个有三个字段的数据结构,这些数据结构包含 Golang 需要操作底层数组的元数据:
这 3 个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量).
nil 和空切片 。
有时,程序可能需要声明一个值为 nil 的切片(也称nil切片)。只要在声明时不做任何初始化,就会创建一个 nil 切片.
在 Golang 中,nil 切片是很常见的创建切片的方法。nil 切片可以用于很多标准库和内置函数。在需要描述一个不存在的切片时,nil 切片会很好用。比如,函数要求返回一个切片但是发生异常的时候。下图描述了 nil 切片的状态:
空切片和 nil 切片稍有不同,下面的代码分别通过 make() 函数和字面量的方式创建空切片:
空切片的底层数组中包含 0 个元素,也没有分配任何存储空间。想表示空集合时空切片很有用,比如,数据库查询返回 0 个查询结果时.
不管是使用 nil 切片还是空切片,对其调用内置函数 append()、len() 和 cap() 的效果都是一样的.
通过切片创建新的切片 。
切片之所以被称为切片,是因为创建一个新的切片,也就是把底层数组切出一部分。通过切片创建新切片的语法如下:
其中 i 表示从 slice 的第几个元素开始切,j 控制切片的长度(j-i),k 控制切片的容量(k-i),如果没有给定 k,则表示切到底层数组的最尾部。下面是几种常见的简写形式:
让我们通过下面的例子来理解通过切片创建新的切片的本质:
执行上面的代码后,我们有了两个切片,它们共享同一段底层数组,但通过不同的切片会看到底层数组的不同部分:
注意:截取新切片时的原则是 "左含右不含"。所以 myNum 是从 num 的 index=1 处开始截取,截取到 index=3 的前一个元素,也就是不包index=3 这个元素.
所以,新的 myNum 是由 num 中的第2个元素、第3个元素组成的新的切片构,长度为 2,容量为 4。切片 num 能够看到底层数组全部 5 个元素的容量,而 myNum 能看到的底层数组的容量只有 4 个元素。num 无法访问到底层数组的第一个元素。所以,对 myNum 来说,那个元素就是不存在的.
共享底层数组的切片 。
需要注意的是:现在两个切片 num 和 myNum 共享同一个底层数组。如果一个切片修改了该底层数组的共享部分,另一个切片也能感知到:
把 35 赋值给 myNum 索引为 1 的元素的同时也是在修改 num 索引为 2 的元素:
切片只能访问到其长度内的元素 。
切片只能访问到其长度内的元素,试图访问超出其长度的元素将会导致语言运行时异常。在使用这部分元素前,必须将其合并到切片的长度里。下面的代码试图为 num 中的元素赋值:
上面的代码可以通过编译,但是会产生运行时错误:panic: runtime error: index out of range 。
切片扩容 。
相对于数组而言,使用切片的一个好处是:可以按需增加切片的容量.
Golang 内置的 append() 函数会处理增加长度时的所有操作细节。要使用 append() 函数,需要一个被操作的切片和一个要追加的值,当 append() 函数返回时,会返回一个包含修改结果的新切片.
函数 append() 总是会增加新切片的长度,而容量有可能会改变,也可能不会改变,这取决于被操作的切片的可用容量.
执行上面的代码后的底层数据结构如下图所示:
此时因为 myNum 在底层数组里还有额外的容量可用,append() 函数将可用的元素合并入切片的长度,并对其进行赋值.
由于和原始的切片共享同一个底层数组,myNum 中索引为 3 的元素的值也被改动了.
如果切片的底层数组没有足够的可用容量,append() 函数会创建一个新的底层数组,将被引用的现有的值复制到新数组里,再追加新的值,此时 append 操作同时增加切片的长度和容量:
当这个 append 操作完成后,newSlice 拥有一个全新的底层数组,这个数组的容量是原来的两倍:
函数 append() 会智能地处理底层数组的容量增长.
在切片的容量小于 1000 个元素时,总是会成倍地增加容量。一旦元素个数超过 1000,容量的增长因子会设为 1.25,也就是会每次增加 25%的容量(随着语言的演化,这种增长算法可能会有所改变).
总结 。
切片为我们操作集合类型的数据提供了便利的方式,又能够高效的在函数间进行传递,因此在代码中切片类型被使用的相当广泛.
原文链接:https://mp.weixin.qq.com/s/NX95bhXS2o9zhDQk47-XCA 。
最后此篇关于Go 切片只需这一篇!的文章就讲到这里了,如果你想了解更多关于Go 切片只需这一篇!的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个只是 HTML 页面的应用程序。这会从另一台服务器调用 API 来获取/发送数据。这是我的问题。 我们如何维护登录用户的 session ?那就是,怎样才能阻止他在不登录的情况下访问其他页面进
这个问题在这里已经有了答案: Margin on child element moves parent element (18 个答案) 关闭 6 年前。 好吧,现在我遇到了这个问题,我只想调整“c
话说人生苦短,我用Python。 如果学python不是为了下载这些视频,那将毫无意义! 啊呸,老色批 咳咳,我们开始正题。 一、事前前奏 首先没装Python、pycharm的铁子先自己安装一下,我
问题陈述: 给定两张图像,例如下面布拉德·皮特的两张图像,请判断图像中是否包含同一个人。困难在于,我们每个人只有一张引用图像,并且如何确定任何其他传入图像是否包含同一个人或没有。 一些研究: 有几种不
我们的新闻源遇到了问题 - 它本质上是一个 Likebox 插件,可以节省更新网站和 Facebook 页面的麻烦。 Facebook 页面使用 iframe 填充新闻源。如果网站的浏览者未登录 Fa
任何人都可以给我一些关于如何使 javascript 计数计时器在 5 分钟后停止的小提示,我尝试过的代码低于我使用的代码,但我只想只用 5 分钟它在 5 分钟后停止。 var sec =
有没有办法为某些内容增加 View 表,或者如果不存在,则添加第一个 View 而不运行 2 个查询。这是我当前有效的代码。 function increment_views($id = null)
是否可以获取用户从天气应用程序中输入的位置(例如“马德里”)的 7 天天气预报,然后将其保存以供以后科学使用?在最好的情况下,我希望稍后有一个 if 语句,如下所示: #define sunny 1
根据外媒 9to5google 的消息,小米电视棒现已通过 FCC 的审批,可能很快在美国上市。 IT之家了解到,这款 FCC 认证的小米电视棒的型号为 MITVMDZ24AA,是两款小米 M
Visual Studio 2010 - 发布版 - 打开一个 xaml 文件大约需要 5 秒钟。 它在某些机器上执行,而不是所有机器! .cs 文件立即打开。它只发生在 XAML 上。 我们尝试了以
我正在解决“HackerRank”页面上的一个问题,特别是名为“追加和删除”的问题,但我无法使所有情况都正确。 https://www.hackerrank.com/challenges/append
我正在尝试从头开始构建幻灯片放映。我只想使用 javascript,而不使用 jquery。 到目前为止,当我单击“上一页”按钮时,它只会向左 move 50px 一次。如何让它每次单击“上一个”按钮
我有一个 Ionic 应用程序,我希望它连接到我的套接字。这在 SignalR 预览中工作得很好,它基本上仍然有效,但由于某种原因需要 2 分钟才能连接...... 连接时我也遇到一些错误: 这是我的
我对 Silverlight 和 MVVM/Prism 模式相当陌生,所以这可能是一个愚蠢的问题。 我有一个 View ,其中包含自定义控件。这些自定义控件实际上也是 View ,并且有 ViewMo
我在 python 上使用一些 DataFrame,我遇到了一种情况,我必须在相同的 if 条件下同时更改 2 列。我解决了我的问题,但我并没有只用一个 if 条件。 我试图搜索一些相关内容,但我只在
为什么scanf()在读取double时需要“%lf”中的l ,当 printf() 可以使用“%f”时,无论其参数是 double 还是 float ? 示例代码: double d; scanf(
为什么scanf()在读取double时需要“%lf”中的l ,当 printf() 可以使用“%f”时,无论其参数是 double 还是 float ? 示例代码: double d; scanf(
我是一名优秀的程序员,十分优秀!