【Go专家编程——常见数据结构slice的实现原理】

1. slice

slice又称动态数组,依托数组实现,可以方便地进行扩容和传递,实际使用中比数组更灵活。

2.基本操作

2.1 初始化

// 1.变量声明,此时为nil
var s []int
// 等价于使用new函数
s := *new([]int)
// 2.字面量,空切片是指长度为空,不是nil。
s1 := []int{}//空切片
s2 := []int{1,2,3}
// 3.内置函数make()
s1 := make([]int,12)//指定长度
s2 := make([]int,10,100)//指定长度和空间
// 4.切取
array := [5]int{1,2,3,4,5}
s1 := array[0:2] //从数组切取
s2 := s1[0:1] //从切片切取
//
  • 声明长度为0的切片时,推荐使用变量声明获得一个nil切片,因为空切片不需要分配内存
  • 使用make可以创建切片,切片元素均初始化为对应类型的零值。推荐指定长度的同时指定预估空间,可有效减少切片扩容时内存分配及拷贝次数。

2.2 切片操作

可以使用内置函数append()用于向切片中追加元素

s := make([]int, 0)
s = append(s, 1)	//添加一个元素
s = append(s, 2,3,4)	//添加多个元素
s = append(s, []int{5,6}...)	//添加一个切片

当切片函数空间不足时,append()会先创建新的大容量切片,添加元素后再返回新切片。

由于切片的本质为结构体,结构体中直接存储了长度和容量,如源码所示。

3. 实现原理

3.1 数据结构

type slice struct{array unsafe.Pointer	//指向底层数组len int		//切片长度cap int		//底层数组的容量
}

3.2 切片操作

  • 使用make创建slice
  • 使用数组创建slice,slice将与原数组共用一部分内存
  • slice扩容
    • 扩容实际上是重新分配一块更大的内存,将原slice数据拷贝进新slice,然后返回新slice,扩容后再将数据追加上去。
    • 扩容原则:容量小于1024.新容量扩大到原来的2倍。大于1024,扩大到原来的1.25倍。
  • slice拷贝
    • copy()内置函数拷贝两个切片时会将原切片的数据逐个拷贝到目标切片指向的数组中,拷贝的数量取两个切片长度的最小值。
    • 拷贝不会发生扩容

4. 切片表达式

4.1 简单表达式

a[low : high]

  • 底层数组共享
    • 当使用简单表达式生成的切片,与原数组或切片共享底层数组
  • 边界问题
    • 如果简单表达式截取的对象为字符串或数组,那么a[low:high]中的low和high需要满足0<=low<=high<=len(a)
    • 如果简单表达式截取的对象为切片,那么a[low:high]中的low和high需要满足0<=low<=high<=cap(a)
  • 切取string时会产生一个新的string
  • low和high均有默认值,low为0,high为len(a)

4.2 扩展表达式

简单表达式生成的新切片与原数组或切片共享底层数组避免了拷贝元素,但节约内存的同时也会带来一定的风险。
新切片b(b:=a[low:high])不仅可以读写a[low]至a[high-1]之间的所有元素,而且在使用append(b,x)的时候,可能会覆盖a[high]及后面的元素。
这些操作往往是非预期的

在Go1.2中提供了a[low:high:max]来限制新切片的容量
扩展表达式中的max用来限制新生成的切片的容量cap,新切片的容量为max-low。
表达式中的各参数需要满足0<=low<=high<=max<=cap(a)
当max==high时就不会发生之前的情况。

  • 扩展表达式中只有low是可以省略的
  • 扩展表达式可以用于数组和切片,但是不能用于字符串

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

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

相关文章

20240508金融读报:风控分析拟人化国际信贷创新

1、金融借助AI等技术实现拟人化二次提升-风控分析拟人化&#xff1a;网商银行大雁系统搭建产业链图谱并利用大模型对齐分析&#xff1b;大山雀系统光谱识别作物种植、生长情况&#xff0c;预测产量从而决定授信额度&#xff1b;百灵系统识别理解客户信贷诉求&#xff08;感觉是…

VBA技术资料MF152:列出工作表中所有单元格的注释

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

FreeRTOS的任务详解、创建与删除

目录 1、任务详解 1.1 什么是任务&#xff1f; 1.2 任务的特点 1.3 任务的状态 1.4 任务的优先级 1.5 任务的堆和栈 2、任务的创建与删除 2.1 相关API 2.2 函数解析 2.2.1 xTaxkCreate() 2.2.2 xTaskCreateStatic() 2.2.3 vTaskDelete() 3、实战案例 3.1 创建两个…

JavaSwing课程设计-实现一个计算器程序

通过JavaSwing技术来实现计算器小程序&#xff0c;效果如下。 源码下载链接 源码下载 博主承诺真实有效&#xff0c;私信可提供支持

Android广播demo(系统广播,自定义广播)

1 系统广播demo 1.1 BootReceiver 的广播接收器类&#xff1a; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast;public class BootReceiver extends BroadcastReceiver {Overridep…

JavaEE 多线程详细讲解(2)

1.线程不安全分析 &#xff08;1&#xff09;线程不安全的主要原因就是&#xff0c;系统的抢占式执行&#xff0c;对于内核设计者来说&#xff0c;这是非常方便的一个执行方式&#xff0c;但是这却却导致线程不安全的问题&#xff0c;也有不抢占执行的系统&#xff0c;但是这种…

存储或读取时转换JSON数据

一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题&#xff1a; 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …

STL速查

容器 (Containers) 图解容器 支持随机访问 stringarrayvectordeque支持支持支持支持 string 类 构造函数 string(); ------创建一个空的字符串 例如: string str;string(const char* s); ------使用字符串s初始化string(const string& str); ------拷贝构造 赋值操作…

欧拉角(Euler)和四元数(Quaternion)

欧拉角-Euler 欧拉角是三个角度参数&#xff0c;它们描述了一个物体围绕三个主轴X、Y和Z顺序旋转的情况。三个角分别对应于偏航&#xff08;Yaw&#xff09;、俯仰&#xff08;Pitch&#xff09;和翻滚&#xff08;Roll&#xff09;。 偏航(Yaw)&#xff1a;绕Y轴的旋转&…

Android GPU渲染屏幕绘制显示基础概念(1)

Android GPU渲染屏幕绘制显示基础概念&#xff08;1&#xff09; Android中的图像生产者OpenGL&#xff0c;Skia&#xff0c;Vulkan将绘制的数据存放在图像缓冲区中&#xff0c;Android中的图像消费SurfaceFlinger从图像缓冲区将数据取出&#xff0c;进行加工及合成。 Surface…

OpenMVS学习笔记(一):WSL编译安装测试

1.CUDA和CUDNN安装 [1] WSL版本cuda安装&#xff1a; >> wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin >> sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600 >> wg…

Vue 数据校验

使用 插件 和 mixin进行数据校验 使用mixin 进行数据校验 <script>// plugin 插件 数据校验// 创建 vue实例const app Vue.createApp({data() {return{name:dell,age: 28}},methods: {handleClick() {this.show !this.show;}},// 数据校验 agerules: {age: {validat…

7个AI驱动的3D模型生成器

老子云AI生成3D模型https://www.laozicloud.com/aiModel 在快速发展的技术世界中&#xff0c;人工智能 (AI) 已经改变了游戏规则&#xff0c;尤其是在 3D 对象生成领域。 AI 驱动的 3D 对象生成器彻底改变了我们创建和可视化 3D 模型的方式&#xff0c;使该过程更加高效、准确…

Star-CCM+通过将所有部件创建一个区域的方式分配至区域后子区域的分离,子区域材料属性的赋值,以及物理连续体的创建方法介绍

前言 上次介绍了将零部件分配至区域的方法与各个方法之间的区别&#xff0c;本文将继续上次的讲解&#xff0c;将其中的“将所有部件分配至一个区域”的应用进行补充。 如下图所示&#xff0c;按照将所有部件创建一个区域的方式分配至区域后&#xff0c;在区域下就会有一个区域…

toB、toC、toD、B2B、C2C、O2O、B2C、P2P到底是什么?

toB、toC、toD到底是什么&#xff1f; toB&#xff08;Business&#xff09;&#xff1a;面向企业用户&#xff0c;例如OA办公系统 toC&#xff08;Consumer&#xff09;&#xff1a;主要是面向个人、客户&#xff0c;例如王者荣耀 toD&#xff08;Developer&#xff09;&…

WPF中ObservableCollection

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;ObservableCollection<T> 是一个非常重要的类&#xff0c;它用于实现动态数据绑定功能。这个类位于 System.Collections.ObjectModel 命名空间中&#xff0c;是 ICollection<T>, IList…

初识微前端

微前端&#xff1a;微前端是一种软件架构模式&#xff0c;旨在解决大型前端应用程序开发和维护中的复杂性问题。它将前端应用程序拆分成更小的、独立的部分&#xff0c;每个部分可以由不同的团队开发、测试、部署和维护。这些独立的部分可以是单独的应用程序或者功能模块&#…

java:遍历目录文件

/*** 通过递归遍历目录下的所有内容&#xff0c;并把所有文件的绝对路径输出在控制台** 思路&#xff1a;* 1.根据给定的路径创建一个File对象* 2.定义一个方法&#xff0c;用于获取给定目录下所有内容&#xff0c;参数为第一步创建的file对象* 3.获取给定的File目录下的文件或…

若依集成mybatis-plus 超详细教程(亲测可用)

文章目录 简介步骤第一步第二步第三步第四步第五步第六步 使用QueryWrapperservice层impl 实现接口类层Mapper层 简介 话不多说 直接跟着下面的教程操作&#xff0c;如果有报错私信我&#xff0c;或者通过博文下面的微信名片加我微信&#xff0c;免费解答哦&#xff01; 步骤 …

代码随想录Day 42|Leetcode|Python|121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从…