Go语言程序设计(五)切片

一、切片的定义

        在Go语言中,切片(Slice)是数组的一个引用,它会生成一个指向数组的指针,并通过切片长度关联到底层数组部分或者全部元素。切片还提供了一系列对数组的管理功能(append、copy),可以随时动态扩充存储空间,并且可以被随意传递而不会导致所管理的数组元素被重复复制。根据以上特征,切片通常被用来实现变长数组,而且操作灵活。

切片的数据结构原型定义如下:

src/ pkg/ runtime/ runtime. h

struct Slice
{                   //must not move anythingbyte* array;    //actual dataunit32 len;     //number of elementsunit32 cap;     //allocated number of elements
};

由切片数据结构的原型定义可以看到,它抽象为以下三个部分:

  • 指向被引用的底层数组的指针。
  • 切片中元素的个数。
  • 切片分配的存储空间。

二、切片的声明与创建

切片声明与创建的方法有三种:基于底层数组创建、直接创建或使用make()函数创建。

1、基于底层数组创建

在创建切片时,可以基于一个底层数组,切片可以只使用数组的一部分元素或所有元素,甚至可以创建一个比底层数组还要大的数组切片,因为切片可以动态增长。创建切片的格式如下:

var sliceName [ ]dataType

说明:

  1. 切片名的命名规则和变量名相同,遵循标识符命名规则。
  2. 在创建切片时,不要指定切片的长度。
  3. 切片的类型可以是Go语言的任何基本数据类型。

例如:

var slice1 [] int

        上例中定义了一个整型切片slicel,注意不要指定切片长度,如果指定了长度就成了定义数组了。当一个切片定义好以后,如果还没有被初始化,默认值为nil, 而且切片的长度为0。切片的长度可以使用内置函数len()获取,还可以使用内置函数cap()获取切片的内存容量。

所以,当一个切片定义好以后,还要对切片进行初始化,这样切片才可用。对于上例,假如已经定义了一个整型数组array1,则切片slice1的初始化方式如下:

slice1 = array1[start : end]

        从上式可以看到,Go语言支持以array1[start : end]的方式基于一个底层数组来生成切片,即切片引用的数组元素由array1[start]到 array1[end],但不包含array1[end]。

如果要引用底层数组的所有元素,可采取的方式如下:

slicel = array1
slice1 = array1[ :]
slicel = array1[0: len(array1)] 

2、直接创建切片

直接创建切片,即在定义切片的时候初始化切片元素,例如:

var slice1 =[]int{1,2,3,4,5}

3、使用make函数创建切片

内置函数make()用于灵活的创建切片

var slicel = make([]int,5)

上式创建了一个有5个元素的整型切片slicel,元素的初值为0。
在使用make()函数创建切片时,还可以为切片元素预留存储空间。例如:

var slice1 = make([]int, 5,10)

上式表示,创建整型切片slice1,元素个数为5,元素初值为0,并预留10个元素的存储空间。
 

三、切片元素的访问与遍历

        切片元素的遍历和数组元素的遍历一样,要通过元素下标访问,另外也可以使用关键字range遍历所有切片元素。切片元素访问的一般格式如下:

sliceName [sliceIndex]

遍历同数组,使用range关键字表达式,有两个返回值,第一个是元素的下标,第二个是元素的值。

四、切片的操作

1、切片元素的增加

        可以使用append()函数向切片尾部添加新元素,这些元素保存到底层数组。append并不会影响原来切片的属性,它返回变更后新的切片对象。

        与数组相比,除了都有长度(length)以外,切片多了一个容量(capacity)的概念,即切片中元素的个数和分配的存储空间是两个不同的值。如果在增加新元素时超出cap的限制,则底层会重新分配一块“够大”的内存,一般来说是将原来的内存空间扩大二倍,然后再将数据从原来的内存复制到新的内存块。

2、切片元素的复制

        使用切片长时间引用“超大”的底层数组,会导致严重的内存浪费。可以新建一个小的slice对象,然后将所需的数据复制过去。函数copy()可以在切片之间复制元素,能够复制的数量取决于复制方和被复制方的长度值,通常取最小值。需要注意的是,在同一底层数组的不同切片间复制元素时,元素位置会发生重叠。

//切片的复制
package mainimport("fmt" 
)func main() {var slicel= []int{1,2,3,4,5,6,7,8,9,10}var slice2 = make([ ] int,3, 5)var n int//只能复制三个元素n= copy(slice2,slice1)fmt. Println(n, slice2, len( slice2), cap(slice2))//slice3和slice1指向同一底层数组slice3 : = slice1[3:6]//复制后元素重叠n= copy(slice3, slice1[1:5])fmt.Println(n, slicel, slice3)
}

编译并运行程序输出结果为:

3 [1 2 3] 3 5
3 [1 2 3 2 3 4 7 8 9 10] [2 3 4]

        通过输出结果可以看出,在将slice1复制到slice2时,由于slice2的长度最小为3,所以只能将slice1的前三个元素复制给slice2。而将slicel1复制到slice3 时,由于slicel1和slice3指向同一个底层数组,所以复制后元素重叠。slice3刚创建时,它引用的是底层数组的[4,5,6]三个元素,复制后slice1将[2,3,4]三个元素复制给slice3 ,所以最后slice3 的元素[2,3,4]覆盖了slice1的元素[4,5,6]。

3、排序和搜索切片

        标准库中的sort包提供了对整型、浮点型和字符串类型切片进行排序的函数,检查一个切片是否排序好的函数,以及使用二分搜索算法在一个有序切片中搜索-一个元素的函数。 同时提供了通用sort.Sort ()和sort.Search ()函数,可用于任何自定义的数据。这些函数在表4-2中有列出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/15180.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++数据结构笔记(7)——队列的顺序结构实现

1.队列&#xff0c;和现实生活中的规则类似&#xff0c;先进先出 2.队尾只允许元素进入&#xff0c;队头只允许元素退出 3.用数组来实现队列的顺序存储&#xff0c;无论哪一段都可以作为队头或者队尾 SeqQueue.h头文件 #ifndef SEQQUEUE_H #define SEQQUEUE_H #include<…

Linux——进程信号详解

目录 一.进程信号的理解 1.1定义&#xff1a; 1.2举例&#xff1a; 1.3总结&#xff1a; 二.进程信号地使用&#xff1a; 2.1信号种类&#xff1a; 2.2而操作系统向进程发送信号地方式有四种&#xff1a; 2.2.1以键盘的方式向进程发送信号 接下来介绍一个系统调用函数sign…

chrome开发调试小技巧—Replay XHR(重新请求)

一、需求 想要验证一个ajax请求&#xff0c;需要每次都需要在页面点几次才会触发或者刷新页面&#xff0c;着急调试看效果时&#xff0c;可以通过chrome的Replay XHR功能直接同参数重新请求ajax 二、实现 chrome调试工具network下找到要重新发起的ajax请求&#xff0c;右键找…

python读写excel利器:xlwings从入门到精通

python读写excel利器&#xff1a;xlwings 从入门到精通 目录 安装和使用 基础操作 操作工作簿操作工作表读取单元格写入(单元格赋值)range的操作&#xff08;range常用的api&#xff09; 写入一行或一列Excel数据(函数式&#xff09;使用range(\A1\).api.AddComment(\comments…

力扣 332. 重新安排行程

题目来源&#xff1a;https://leetcode.cn/problems/reconstruct-itinerary/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a; 这道题目有几个难点&#xff1a; 一个行程中&#xff0c;如果航班处理不好容易变成一个圈&#xff0c;成为死循环。解决&am…

ue4:Dota总结_BP_CameraPawn篇

设计wasd移动&#xff1a; 鼠标拖动视口&#xff1a; 鼠标滚轮调整远近&#xff1a; Beginplay&#xff1a; qe按键旋转&#xff1a; 变量&#xff1a;

word@制表位和列数据对齐@填空下划线制作

文章目录 refs制表位(tab stop)制表位类型 制作对其的下划线填空表单&#x1f47a;利用前导符代替下划线制作待填空下划线 制表位对其列数据模拟简单表格测试数据设置引线使用标尺设置 FAQ refs Insert or add tab stops - Microsoft SupportUsing the ruler in Word - Micros…

【Django】列表数据Paginatior分页,动态返回页码,显示当前页、总页数、跳转页

问题 1、当返回数据较多,如设置每页展示10条,数据接近200条,返回页码范围1~20,前端每个页码都显示的话,就会出现页码超出当前页面,被遮挡的页码无法操作和显示不美观; 2、列表的所在页码,总分页数,跳转不在动态页面的页数 解决 在使用paginator转化为Page对象后,获…

从零开始 Spring Boot 63:Hibernate 继承映射

从零开始 Spring Boot 63&#xff1a;Hibernate 继承映射 图源&#xff1a;简书 (jianshu.com) 关系型数据库设计中是不存在继承概念的&#xff0c;但实体类可以用继承来组织代码结构&#xff0c;所以需要用一种方式将实体类的继承结构映射到表结构。 本文将介绍几种在 JPA&a…

MySQL逻辑架构

MySQL逻辑架构 1. MySQL逻辑架构1.1 连接层1.2 服务层1.3 引擎层 2. SQL执行流程2.1 SQL执行流程2.2 查看SQL执行流程2.3 SQL语法顺序 1. MySQL逻辑架构 分为Connectors层、MySQL服务器对应架构、存储层&#xff1b;MySQL服务器对应架构分为连接层、服务层、引擎层&#xff0c…

RabbitMQ系列(26)--RabbitMQ实现高可用负载均衡

前言&#xff1a;我们以往只能连接一个指定的队列&#xff0c;不能自由地连接其他的队列&#xff0c;当我们连接的那个指定队列宕机了&#xff0c;生产者和消费者都没办法往队列发送消息和消费消息&#xff0c;而且生产者和消费者也不能自动的连接到其他正常运行的队列&#xf…

sqlite维护命令复习学习

前面已经看了一些sqlite命令&#xff0c;例如查看表名&#xff0c;查看表结构等&#xff1b;下面继续看一下&#xff1b; 查看全部表名&#xff1b; 查看单个或全部的表结构&#xff1b; 输出表结构和数据&#xff1b; 使用.output 把查询结果定向到1.txt&#xff1b; 重新定向…