go中的切片
demo1:切片定义的几种方式
package mainimport "fmt"/*
切片定义的几种方式数组和切片区别:
使用数组传参是值传递,而使用切片传参是引用传递
数组定义好长度之后不可修改,而切片可以理解为动态数组,长度可修改*/func main() {//方法1:直接创建s1 := []string{"1", "2", "3"}fmt.Printf("%T\n", s1)fmt.Println(len(s1))fmt.Println(s1)fmt.Println("--------------------------------------")//方法2:使用make定义,但是需要加上长度,cap可加可不加s2 := make([]string, 3) //s2:=make([]string, 3,5) 加cap写法fmt.Printf("%T\n", s2)fmt.Println(len(s2))fmt.Println(s2)fmt.Println("--------------------------------------")//方法3:数组变切片arr := [3]string{"1", "2", "3"}s3 := arr[1:2]fmt.Printf("%T\n", s3)fmt.Printf("%T\n", arr)fmt.Println(len(s3))fmt.Println(s3)fmt.Println("--------------------------------------")//方法4:news4 := new([]string)fmt.Printf("%T\n", s4)//fmt.Println(len(s4)) //没有长度fmt.Println(s4) //&[]}
demo2: 切片的基本操作
package mainimport "fmt"/*
切片的基本操作:添加、复制、合并、删除
*/func main() {s1 := []string{"1", "2", "3"}//添加s1 = append(s1, "4", "5")fmt.Println(s1)//复制s2 := []string{}copy(s2, s1)fmt.Println(s2) //这里s2为空,因为没定义长度//拷贝时,目标对象长度为多少就只能复制多少s3 := make([]string, len(s1))copy(s3, s1)fmt.Println(s3)//把两个切片合并s2 = append(s1, s3...) //省略号是规定的参数fmt.Println(s2)//数组中删除元素:先把数组变成切片,再把两个切片合并s4 := s2[:]s4 = append(s2[0:2], s2[4:]...)fmt.Println(s4)
}
demo3: 切片的cap和len
package mainimport "fmt"/*
切片的容量(cap)和长度(len)slice的底层是使用数组实现的,同一个数组的切片会共享内存,但如果切片扩容超过切片的原有容量cap会触发扩容机制,该切片就会自己独立开辟全新内存空间。slice的append扩容问题:扩容阶段因为需要整体开辟全新的内存空间,因此扩容阶段会影响速度。python的list中底层实际上也是数组,也会面临扩容影响速度的问题。python的同一list中可以存不同的数据类型。
*/func main() {//不设置cap时,len和cap大小一致s1 := []string{"1", "2", "3"}fmt.Println(len(s1)) //3fmt.Println(cap(s1)) //3s2 := make([]int, 5) fmt.Println(len(s2)) //3fmt.Println(cap(s2)) //3s3 := make([]int, 5, 8) //设置了容量capfmt.Println(len(s3)) //5fmt.Println(cap(s3)) //8//通过数组取切片:cap为切片起始位置之后的数组长度s4 := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s5 := s4[2:5] fmt.Println(len(s5)) //3fmt.Println(cap(s5)) //8//append函数遇到make问题:如果用make创建切片时定义了长度,append操作会在原有元素之后进行插入。如果没有定义长度,append操作则是对默认元素0进行替换s6 := make([]int, 3)s6 = append(s6, 1)fmt.Println(s6) //[0 0 0 1]s7 := make([]int, 0)s7 = append(s7, 1)fmt.Println(s7) // [1]}
demo4:切片扩容
案例1:
package mainimport ("fmt"
)func main() {data := [...]int{0, 1, 2, 3, 4, 10: 0} //数组s := data[:2:3]fmt.Println(s)fmt.Println(len(s), cap(s))s = append(s, 100, 200, 300) // 一次 append 三个值,超出 s.cap 限制。fmt.Println(s, data) // 重新分配底层数组,与原数组无关。fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针。}
从输出结果可以看出:append 后的 s 被重新分配了底层数组(也就是说 s 的底层数组不再是 data,那么修改 s 的值不会再影响 data,它们不再有关联),并把原数组中的值拷贝到新数组中。这是因为超出了原切片的容量。在上例中,如果只追加一个值,则不会超过 s.cap 限制,也就不会重新分配。
切片的自动扩容策略是这样的:(文章:简单说说go语言Slice的底层实现_Liuzhiwang29的博客-CSDN博客 简单说说go语言Slice的底层实现 通过分析源码对这一点提出了质疑)通常 以 2 倍容量 进行扩容,并重新分配底层数组(新底层数组的容量也变大)。如果切片的容量小于 1024 个元素,扩容的时候就翻倍增加容量。一旦元素个数超过 1024 个元素,那么增长因子就变成 1.25 ,即每次增加原来容量的四分之一。注意:扩容扩大的容量都是针对原来的容量而言的,而不是针对原来数组的长度而言的。
所以,在大批量添加数据时,建议 一次性分配足够大的空间 ,以减少内存分配和数据复制开销。或 初始化足够长的 len 属性,改用索引号进行操作。及时释放不再使用的 slice 对象,避免持有过期数组,造成 GC 无法回收。
slice中 cap 重新分配规律:
package mainimport ("fmt"
)func main() {s := make([]int, 0, 1)fmt.Println(s)c := cap(s) //计算容量fmt.Println(c)for i := 0; i < 50; i++ {s = append(s, i) //按理说 append 第2个元素时就超出了cap,这时会重新分配底层数组来扩大capif n := cap(s); n > c {fmt.Printf("cap: %d -> %d\n", c, n)c = n}}}
输出结果:
[]
1
cap: 1 -> 2
cap: 2 -> 4
cap: 4 -> 8
cap: 8 -> 16
cap: 16 -> 32
cap: 32 -> 64
我们可以发现,通常以 2 倍的 cap 重新分配。
提一嘴哈,如果给切片 append 元素时,不超切片容量就没事,操作的还是原数组:
package mainimport ("fmt"
)func main() {data := [...]int{0, 1, 2, 3, 4, 10: 0} //数组s := data[:2:5] //将切片容量扩大到5fmt.Println(s)fmt.Println(len(s), cap(s))s = append(s, 100, 200, 300) // 一次 append 三个值,这次没超出 s.cap 限制。fmt.Println(s, data) fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针}
输出结果:
[0 1]
2 5
[0 1 100 200 300] [0 1 100 200 300 0 0 0 0 0 0]
0xc00004a060 0xc00004a060
案例2:
package mainimport "fmt"//slice的扩容func main() {arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}s1 := arr[2:6] s2 := s1[3:5]fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1)) //2,3,4,5fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2)) //5,6,为什么s2中取到6,是因为slice支持向后扩容//slice的操作:向slice中添加元素s3 := append(s2, 10)s4 := append(s3, 11)s5 := append(s4, 12)fmt.Println("s3,s4,s5:", s3, s4, s5)fmt.Println("arr:", arr) //为什么没有11,12? 是因为不能超过cap,如果超过cap则会重新分配一个数组进行存储}
相关文章:
go中的切片
demo1:切片定义的几种方式 package mainimport "fmt"/* 切片定义的几种方式数组和切片区别: 使用数组传参是值传递,而使用切片传参是引用传递 数组定义好长度之后不可修改,而切片可以理解为动态数组,长度可修改*/func …...

C++笔记之单例通过GetInstance传递参数
C笔记之单例通过GetInstance传递参数 code review! 文章目录 C笔记之单例通过GetInstance传递参数例1.普通指针的单例例2.结合智能指针和std::call_once例3.编译不通过的错误例子,在GetInstance内不可以使用std::make_shared来创建对象 例1.普通指针的单例 运行 …...

1688API技术解析,实现获得1688商品详情
要实现获得1688商品详情,你需要使用1688 API。1688 API是阿里巴巴旗下的开放平台,它提供了一套丰富的接口,可以让开发者通过编程的方式获取到1688网站上的商品信息。 首先,你需要在阿里开放平台注册一个账号,并创建一…...

【Java 动态数据统计图】动态X轴二级数据统计图思路Demo(动态,排序,动态数组(重点推荐:难)九(131)
需求: 1.有一组数据集合,数据集合中的数据为动态; 举例如下: [{province陕西省, city西安市}, {province陕西省, city咸阳市}, {province陕西省, city宝鸡市}, {province陕西省, city延安市}, {province陕西省, city汉中市}, {pr…...

C#将text文本中的单双行分开单独保存
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 文本的分割1.设定text文件的名称为02.文本导出 文本的分割 1.设定text文件的名称为0 代码如下: using System; using System.Collections.Generic; us…...
深入理解 Go 语言中的 iota
iota是go语言的常量计数器,只能在常量表达式中使用,iota在const关键字出现时将被重置为0,const中每新增一行常量声明将使iota计数一次,可理解为const语句块中的行索引。它会自动递增,从0开始。 修改步长 尽管默认步长…...

【力扣】55、跳跃游戏
var canJump function(nums){let cover 0;for(let i0;i<nums.length;i){if(i<cover){cover Math.max(nums[i]i,cover);if(cover >nums.length-1){return true;}}}}...
个人与公司合作,怎么代开发票?有哪些优惠政策?
《梅梅谈税》专注于企业税务筹划!助力企业合理、合规、合法进行节税税收筹划! 当下越来越多的个人与公司直接发生业务往来,例如个人给企业提供技术服务,做宣传推广等,业务完成公司给个人支付了相关费用后,…...

什么是计算机视觉,计算机视觉的主要任务及应用
目录 1. 什么是计算机视觉 2. 计算机视觉的主要任务及应用 2.1 图像分类 2.1.1 图像分类的主要流程 2.2 目标检测 2.2.1 目标检测的主要流程 2.3 图像分割 2.3.1 图像分割的主要流程 2.4 人脸识别 2.4.1 人脸识别的主要流程 对于我们人类来说,要想认出身边…...

网易24届内推
【网易】2024届网易互联网秋季校园招聘内推开始啦!给你分享我的专属内推邀请函:https://bole.campus.163.com/campus/home?projectId55&type99&isShare1&boleId7b842acc7c2b42db&boleType2&signatured5f2a3dc23bed70777a8be1a14b49…...

redis 应用 4: HyperLogLog
我们先思考一个常见的业务问题:如果你负责开发维护一个大型的网站,有一天老板找产品经理要网站每个网页每天的 UV 数据,然后让你来开发这个统计模块,你会如何实现? img 如果统计 PV 那非常好办,给每个网页一…...

进程的挂起状态
进程的挂起状态详解 当我们谈论操作系统和进程管理时,我们经常听到进程的各种状态,如“就绪”、“运行”和“阻塞”。但其中一个不那么常被提及,但同样重要的状态是“挂起”状态。本文将深入探讨挂起状态,以及为什么和在何时进程…...

idea 链接mysql连不上
打开文件 C:\Program Files\JetBrains\IntelliJ IDEA 2023.2.1\jbr\conf\security\java.security修改内容 搜索:jdk.tls.disabledAlgorithms 修改 链接地址 在链接后面添加 ?useSSLfalse jdbc:mysql://127.0.0.1:3306/db_admin3?useSSLfalse...

Ubuntu 启动出现grub rescue
一,原因 原因:出现 “grub rescue” 错误通常表示您的计算机无法正常引导到操作系统,而是进入了 GRUB(Grand Unified Bootloader)紧急模式。这可能是由于引导加载程序配置错误、硬盘驱动器损坏或其他引导问题引起…...
go中runtime包里面的mutex是什么?runtime.mutex解析
其实在看go源码的时候,发现除了sync包里有个mutex以外,runtime包里也有一个mutex,这个mutex在runtime很多地方都在用。 这个runtime包里面的mutex的结构如下: 目录: /runtime/runtime2.go 代码: type mutex struct …...

VScode 调试python程序,debug状态闪断问题的解决方法
0. Few words 之前一直在VSCode中debug C和Python的程序没出过闪断的问题,但是最近在另一台电脑上debug,同样的方法,设置launch.json和CMakeList加debug状态等等操作,如我另一篇blog写的一样,可以点这里查看。 但是&a…...

飞桨中的李宏毅课程中的第一个项目——PM2.5的预测
所谓的激活函数,就是李宏毅老师讲到的sigmoid函数 和 hard sigmoid函数 ,ReLU函数那些 现在一点点慢慢探索,会成为日后想都做不到的经历,当你啥也不会的时候,才是慢慢享受探索的过程。 有一说一,用chatGP…...

Qt---对话框 事件处理 如何发布自己写的软件
目录 一、对话框 1.1 消息对话框(QMessageBox) 1> 消息对话框提供了一个模态的对话框,用来提示用户信息,或者询问用户问题并得到回答 2> 基于属性版本的API 3> 基于静态成员函数版本 4> 对话框案例 1、ui界面 …...

【C++】C++ 引用详解 ⑩ ( 常量引用案例 )
文章目录 一、常量引用语法1、语法简介2、常引用语法示例 二、常量引用语法1、int 类型常量引用示例2、结构体类型常量引用示例 在 C 语言中 , 常量引用 是 引用类型 的一种 ; 借助 常量引用 , 可以将一个变量引用 作为实参 传递给一个函数形参 , 同时保证该值不会在函数内部被…...

React原理 - React Reconciliation-下
目录 Fiber Reconciler 【react v16.13.1】 React Fiber需要解决的问题 React Fiber的数据结构 时间分片 Fiber Reconciler 的调度 双缓冲 池概念 小节 练习 Fiber Reconciler 【react v16.13.1】 Fiber 协调 优化了栈协调的事务性弊端引起的卡顿 React Fiber需要解决…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...

CMS内容管理系统的设计与实现:多站点模式的实现
在一套内容管理系统中,其实有很多站点,比如企业门户网站,产品手册,知识帮助手册等,因此会需要多个站点,甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...