切片的基础知识

在这里插入图片描述

文章目录

    • ● Slice 的底层实现原理?
    • ● array 和 Slice 的区别?
    • ● 拷贝大切片一定比小切片代价大吗?
    • ● Slice 深拷贝和浅拷贝?
    • ● 零切片、空切片、nil切片?
    • ● Slice 的扩容机制?
    • ● Slice 为什么不是线程安全的?如何解决这个问题?
    • ● 参数传递切片和切片指针有什么区别?
    • ● range 遍历切片的时候有什么要注意的?

● Slice 的底层实现原理?

切片是对底层数组的引用,在创建一个切片的时候,Go会自动分配一个底层数组,并维护这个数组的指针、切片的长度和容量。

● array 和 Slice 的区别?

1、数组是固定长度的,不能动态扩容,在编译期就会确定大小,切片是可以自动扩容的。 2、数组是值类型,切片是引用类型,每个切片都引用了一个底层数组,切片本身不能存储任何数据,都是底层数组存储数据,所以修改切片的时候修改的是底层数组中的数据。切片一旦扩容,指向一个新的底层数组,内存地址也就随之改变。

● 拷贝大切片一定比小切片代价大吗?

不一定。切片中的第一个字段是指向切片底层数组的指针,这是切片的存储空间,第二个字段是切片的长度,第三个字段是容量。将一个切片变量分配给另一个变量只会复制三个机器字,大切片跟小切片的区别无非就是 Len 和 Cap的值比小切片的这两个值大一些,如果发生拷贝,本质上就是拷贝上面的三个字段。

● Slice 深拷贝和浅拷贝?

浅拷贝是创建一个新的切片,但这个新切片仍然引用原切片的底层数组。 深拷贝是创建一个新的切片,并复制原来切片的所有元素到新的切片中。

● 零切片、空切片、nil切片?

零切片
我们把切片内部数组的元素都是零值或者底层数组的内容就全是 nil的切片叫做零切片,使用make创建的、长度、容量都不为0的切片就是零值切片:slice := make([]int,5) // 0 0 0 0 0 slice := make([]*int,5) // nil nil nil nil nil
nil切片
nil切片的长度和容量都为0,并且和nil比较的结果为true,采用直接创建切片的方式或new创建切片的方式:var slice []int var slice = *new([]int)
空切片
空切片的长度和容量也都为0,但是和nil的比较结果为false,因为所有的空切片的数据指针都指向同一个地址 0xc42003bda0;使用字面量、make可以创建空切片:var slice = []int{} var slice = make([]int, 0) 05. 切片的扩容策略

● Slice 的扩容机制?

新申请的容量如果大于当前容量的两倍,会将新申请的容量直接作为新的容量,如果新申请的容量小于当前容量的两倍,会有一个阈值,即当前切片容量小于256时,切片会将当前容量的2倍作为新申请的容量,如果大于等于256,每次容量会增加 (旧容量+3*256)/4。

● Slice 为什么不是线程安全的?如何解决这个问题?

切片的底层数据结构体包括一个指向数组的指针,在多个线程同时对 切片进行操作时会导致竞态条件。(并发读写问题、切片扩容问题) 通过使用适当的同步机制如互斥锁、读写锁,确保对切片的并发访问是安全的,从而避免竞态条件和数据破坏。 (竞态条件是指在并发程序中,由于多个线程或goroutine同时访问或修改共享资源,从而导致程序的执行结果依赖于线程或goroutine的调度顺序,可能产生不确定和错误的结果。)

● 参数传递切片和切片指针有什么区别?

当切片作为参数传递时,其实就是一个结构体的传递,因为Go语言参数传递只有值传递,传递一个切片就会浅拷贝原切片,但因为底层数据的地址没有变,所以在函数内对切片的修改,也将会影响到函数外的切片。
在 Go 语言中,切片虽然是引用类型,但在函数中使用 append 操作时,需要注意一些细节。append 函数可能会导致切片底层数组重新分配内存,从而影响切片的引用传递。
具体来说,当 append 导致切片容量不足而需要扩容时,append 操作会创建一个新的底层数组,并返回新的切片引用。
由于你没有将这个新引用返回给原切片,原切片仍然指向旧的底层数组,因此不会体现出引用传递的效果。
参数传递切片指针就很容易理解了,如果你想修改切片中元素的值,并且更改切片的容量和底层数组,则应该按指针传递。

● range 遍历切片的时候有什么要注意的?

副本与原始切片: 在range遍历中,实际上会创建每个元素的副本。这意味着你在循环中对副本的修改不会影响原始切片。如果需要修改原始切片,应该使用索引来操作。
只读: 默认情况下,range遍历是只读的,不能修改切片的元素。如果尝试在range循环中修改元素值,会引发编译错误。
索引和值的顺序: 在range循环中,索引总是在前,元素值总是在后。如果只需要索引而不需要元素值,可以使用下划线 _ 来忽略元素值。
切片遍历的性能考虑:尽管使用range遍历切片是非常方便的,但在性能方面可能会有一些影响。每次使用range遍历时,都会创建元素的副本,这可能导致额外的内存开销和性能下降。如果在性能敏感的场景下遇到性能问题,你可以考虑使用索引遍历,以避免创建副本。另外,如果需要在遍历时修改切片的元素,也应该使用索引遍历,以确保修改能够直接影响到原始切片。
切片为空: 如果切片为空,使用range遍历不会执行任何循环体,这可能会导致你的代码出现逻辑问题。在使用range之前,最好先检查切片的长度。
切片为nil: 如果切片为nil,使用range遍历会引发运行时错误。同样,遍历之前应该确保切片不为nil。
遍历数组 vs. 切片: 在数组上使用range遍历和在切片上使用range遍历是不同的。对于数组,range返回索引和元素的副本,而在切片上,range返回索引和元素值的副本。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

父子节点内容和个数提取

有时我们需要获得菜单的内容和个数,这个时候通常有父子菜单,那么怎么分别获取到他们呢?以下面的智慧物业管理系统为例,有7个父节点,每个父节点下面有子节点。如何把父节点名称和总数,以及子节点的名称和总数…

Golang-context理解

golang-context笔记整理 golang为何设计context?代码上理解原理空context类cancelCtx类.withcancelctx方法 timerCtx类valueCtx类 golang为何设计context? 有并发特性的语言中,都会有一种说法:创建异步线程或者携程的时候&#x…

在postman中调试supabase的API接口

文章目录 在supabase中获取API地址和key知道它的restfull风格在postman中进行的设置1、get请求调试2、post新增用户调试3、使用patch更新数据,不用put!4、delete删除数据 总结 在supabase中获取API地址和key 首先登录dashboard后台,首页- 右…

OFDM的缺点与关键技术

子载波间干扰英文简写ICI,ICI可能由各种原因引起 在多径信道中,CP小于最大附加时延时收发系统载波频率偏差和采样偏差收发系统相对移动,存在多普勒频移 ICI是制约OFDM系统性能的主要重要因素之一 对频率偏差敏感----->同步技术&#xff0…

Figma-ui设计学习APP Store

Figma汉化:Figma 中文社区_插件组件库,软件汉化教程 - Figma.Cool 选择Chorme汉化版离线包 插件安装: 打开浏览器安装扩展,解压加载进去即可。 打开标尺,设置左右内边距参考线(左21 右356),wi…

同一个excel表格,为什么在有的电脑上会显示#NAME?

一、哪些情况会产生#NAME?的报错 1.公式名称拼写错误 比如求和函数SUM,如果写成SUN就会提示#NAME?报错。 2.公式中的文本值未添加双引号 如下图: VLOOKUP(丙,A:B,2,0) 公式的计算结果会返回错误值#NAME?,这是因为公式中文本…

PostgreSQL的学习心得和知识总结(一百四十七)|深入理解PostgreSQL数据库之transaction chain的使用和实现

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…

反激开关电源反馈电路相关参数选型

Vb的电压正常变化范围是:0-1V(最低0V,由于有稳压管,最高不会超过1V) Vb的电压越高,则输出占空比越大,Vb电压越低,则输出占空比越小 那么Va的正常变化范围应该是:1.4-4.…

文本生成sql模型(PipableAI/pip-sql-1.3b)

安装环境 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 pip install transformers 代码 question "What are the email address, town and county of the customers who are of the least common gender?"sc…

IT专业入门——高考假期预习指南,我来做你的引路人

目录 认识IT知识体系 什么是计算机 按规模、速度和功能分类 按照其工作模式分类 硬件 操作系统 编程语言 对学习语言的一点建议 对于学python的一点看法 网络 数据结构与算法 数据库 Web开发 Web前端 Web后端 基础预习指南 技术路线学习一览 学习资源推荐 刷…

白话负载均衡、正反向代理(入门科普版)

什么是负载均衡?为什么需要负载均衡 从字面上理解,什么是负载,服务器承受访问量的大小是负载,但是单台服务器的访问性能是有限的,最典型的例子就是双十一、春运抢票这种,这时候就需要一种方案来解决这类问…

ARM功耗管理软件之DVFSAVS

安全之安全(security)博客目录导读 思考:功耗管理软件栈及示例?WFI&WFE?时钟&电源树?DVFS&AVS? 目录 一、ARM功耗管理软件之DVFS 二、ARM功耗管理软件之AVS 一、ARM功耗管理软件之DVFS 有一个实现特定…

SparkSQL调优

SparkSQL调优 文章目录 SparkSQL调优Explain 查看执行计划语法执行计划处理流程 资源调优内存说明spark任务提交到yarn上运行命令 CPU优化 SparkSQL语法优化基于RBO优化基于CBO优化广播join方式一:通过参数指定自动广播方式二:强行广播 SMB Join 数据倾斜…

Go线程实现模型-P

P 概述 P是G能够在M中运行关键。Go的运行时系统会适时地让P与不同的M建立或断开关联,以使P中的那些可运行的G能够及时获得,这与操作系统内核在CPU之上实时切换不同进程或线程的情况类似 改变P的数量 改变单个Go程序间拥有的P的最大数量有两种方法 调…

安卓手机的自带录屏在哪里找?5个软件帮助你快速给手机录屏

安卓手机的自带录屏在哪里找?5个软件帮助你快速给手机录屏 在安卓手机上进行屏幕录制是一项非常实用的功能,特别是对于需要录制游戏操作、制作教程或演示的用户来说。虽然部分安卓手机可能已经预装了屏幕录制功能,但有时候这些功能可能隐藏在…

技术派Spring事件监听机制及原理

Spring事件监听机制是Spring框架中的一种重要技术,允许组件之间进行松耦合通信。通过使用事件监听机制,应用程序的各个组件可以在其他组件不直接引用的情况下,相互发送和接受消息。 需求 在技术派中有这样一个需求,当发布文章或…

每日Attention学习7——Frequency-Perception Module

模块出处 [link] [code] [ACM MM 23] Frequency Perception Network for Camouflaged Object Detection 模块名称 Frequency-Perception Module (FPM) 模块作用 获取频域信息,更好识别伪装对象 模块结构 模块代码 import torch import torch.nn as nn import to…

Ubuntu(通用)—网络加固—ufw+防DNS污染+ARP绑定

1. ufw sudo ufw default deny incoming sudo ufw deny in from any to any # sudo ufw allow from any to any port 5353 protocol udp sudo ufw enable # 启动开机自启 # sudo ufw reload 更改后的操作2. 防ARP欺骗 华为云教程 arp -d删除dns记录arp -a显示arp表 ipconfi…

IMU在手语识别中的应用

近期,一款由美国和中国科研团队联合研发的新型的穿戴设备——SignRing,以其独特的IMU(惯性测量单元)技术,为聋哑人士的手语识别带来了革命性的突破。SignRing不仅极大地扩展了手语识别的词汇量,更提高了识别…

C++多态~~的两个特殊情况

目录 1.多态的概念 2.简单认识 (1)一个案例 (2)多态的两个满足条件 (3)虚函数的重写 (4)两个特殊情况 1.多态的概念 (1)多态就是多种形态; …