切片

为什么需要切片

  1. 用于元素的个数不确定,所以无法通过数组的形式来进行统计。此时就需要切片
    切片,也因此可以粗略地理解为动态数组
  2. 数组的长度不能用变量来确定,这时候切片slice也就派上用场了

切片地基本介绍

  1. 切片的英文是slice
  2. 切片是数组的一种引用,这也说明切片是引用类型,在传递时,遵守引用传递的机制
  3. 切片的使用和数组类似,遍历、求长、访问都是一样的
  4. 切片的长度是可变的,因此说切片可以粗略理解为动态数组
  5. 切片定义的语法:
    var 切片名 []类型
    var a []int

切片的快速入门

var arr [5]int = [5]int{1, 2, 45, 6, 3}
a := arr[2:4]
fmt.Println(arr)
fmt.Println(a)
fmt.Printf(“a的长度%d\n”, len(a))
fmt.Printf(“a的容量%d\n”, cap(a))
fmt.Printf(“a指向的地址%v\n”, &a[0])
输出结果为:
[1 2 45 6 3]
[45 6]
a的长度2
a的容量3
a指向的地址0xc000010240

可见,a := arr[2:4],这段代码就是将arr数组的下标为2-3的元素。
其中cap()函数是用来求切片容量的,容量是指切片目前最多能存储的元素个数,并且这个容量是可以动态更改的

切片在内存中的形式

  1. slice在内存中有三个值,一个是slice所指向的第一个元素的地址,一个是这个slice的长度,还有一个是这个slice的容量
  2. 根据这第一个值,我们也很容易判断出slice是引用类型
  3. 其实,我们可以把slice看成一种结构体struct。其由这三个值组成。
    type slice struct {
    array *[n]T // 指向底层数组的指针
    len int // 当前长度
    cap int // 总容量
    }
  4. 另外,值得注意的一点是,由于slice是引用类型,所以当用slice[1]来修改值时,其所指的地址的值发送改变,也就是原数组的内容也会发送改变
    代码用例:
    var arr [5]int = [5]int{1, 2, 45, 6, 3}
    a := arr[2:4]
    fmt.Println(arr)
    fmt.Println(a)
    a[0] = 100
    fmt.Println(arr)
    fmt.Println(a)
    输出结果为:
    [1 2 45 6 3]
    [45 6]
    [1 2 100 6 3]
    [100 6]

切片的使用

  1. 定义一个切片,让切片去引用一个定义好的数组
  2. 用make来创建切片
    基本语法:var 切片名 []类型 = make([]类型,切片长度,切片容量)
    要求:容量必须大于等于长度
    创建完的切片里的元素都是默认值

这样定义出来的切片所指向的数组,是对外隐蔽的,只能通过slice来访问这个数组

  1. 定义切片的时候,直接指定具体的数组
    代码示例:
    func main() {
    var arr []int = []int{1, 2, 41, 21}
    fmt.Printf(“%v\n”, len(arr))
    fmt.Printf(“%v”, arr)
    }
  2. 方式一和方式二的区别:
    方式一:直接引用数组,是要求先定义好了一个数组,这个数组是可见的
    方式二:用make创建切片的同时,也会创建数组,这个数组是由切片在底层进行维护的数组,是不可见的,只能通过slice来对它进行访问修改等

切片的遍历

  1. 传统for循环
  2. for-range语句遍历
    func main() {
    var n [5]int = [5]int{2, 12, 31, 12, 45}
    slice1 := n[1:3]
    for i := 0; i < len(slice1); i++ {
    fmt.Printf("%v “, slice1[i])
    }
    fmt.Println()
    for index, value := range slice1 {
    fmt.Printf(”%v,%v ", index, value)
    }
    }

切片的使用细节和注意事项

  1. 切片初始化时,var slice = arr[start:end]

其中切片slice是从arr数组的start下标开始,到end下标结束,但是不将end下标的元素也囊括在内

  1. 在使用切片时,也只能按照0-len(slice)-1的范围来,不能够直接来越界初始化,需要先动态增长先
  2. slice :=arr[下标1:下标2]
    1. 如果不写下标1,默认是0,从头开始
    2. 如果不写下标2,默认是end,把最后一位元素也算进去
    3. 所以要想表示切片获取整个数组,有如下几种简写
      1. slice :=arr[:]
      2. slice :=arr[0:]
      3. slice :=arr[:len(arr)]
  3. cap是一个内置函数,用于计算切片的容量,也就是最大可以存放多少元素
  4. 切片定义完后,本身还是空的,需要让其引用数组,或者用make函数创建一个空间供切片使用
  5. 切片可以继续切片
  6. append函数
    1. append的用法
      1. slice = append(slice, elem1, elem2, …)

      给slice切片添加后面几个元素,这里的…表示的是省略

      1. slice = append(slice, anotherSlice…)

      在slice后面接收另一个切片,这里的…是不能省略的,表示将后面的切片各个元素拆开加入
      不论append的哪种用法,都必须要有接收,不然相当于没有任何作用,因为append函数并不会去改变原来的切片

    2. 扩不扩容
      1. 当长度在append后>容量时才会扩容,否则不会
        2. 只有在扩容时,才会执行下面的(45678),因为如果不用扩容,就可以直接在原来的切片上更改,不需要额外创建新数组(拥有足够大的容量)
    3. append函数本质就是对数组的扩容
    4. append函数会创建一个新的数组newarr(是扩容后的大小)
    5. 将slice原来的元素拷贝到newarr
    6. 在newarr上添加新元素
    7. 返回新的切片(指向新数组),比如:slice重新引用到newarr
    8. newarr是底层维护的,程序员不可见
  7. 切片的拷贝
    copy函数
    语法copy(para1,para2)
    para1,para2这两个都需要是切片,并且是将para2的内容给到para1里面

此处不在乎二者的长度的大小关系,反正就是逐位去拷贝

拷贝并不会使这两个切片的空间有什么关联,依然是相互独立的

  1. 切片是引用类型,所以传递时遵循引用传递,向函数传递切片时,函数内部对切片的操作,也会对外部操作有影响
    代码示例:
    func test(a []int) {
    a[0] = 100
    }
    func main() {
    var a []int = make([]int, 4, 8)
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    fmt.Println(a)
    test(a)
    fmt.Println(a)
    }
    输出结果:
    [1 2 3 4]
    [100 2 3 4]

string和slice的关系

  1. string的底层是一个byte数组,因此string也可以用切片来处理
  2. string的核心结构:
    type stringStruct struct {
    str unsafe.Pointer // 指向底层字节数组的指针
    len int // 字符串的字节长度(不是字符数)
    }
    这和切片的结构是很像的,只是没有容量,因为数组的容量大小就是长度大小,因为它长度不可变
  3. string本身是不可变的,不能通过str[0]="1"这种类似形式去修改(和java一样)
  4. 如果要修改string的值,需要先将string转换成[]byte或者[]rune,修改完后,再转成string

有中文的情况转成[]rune,因为[]rune是按照字符,一个中文占三四个字节

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

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

相关文章

在labview中实现视频播放

这里分享一个迅雷的视频播放控件APlayer&#xff0c;非常的好用。具体操作步骤如下&#xff1a; 1.下载控件: 首先下载http://aplayer.open.xunlei.com/codecs.zip&#xff0c;将codecs文件解压后打开&#xff0c;按快捷键contrlA,随后contrlc复制里面所有的文件&#xff1b;…

ubuntu 22.04 使用yaml文件 修改静态ip

前提&#xff1a; 启动服务 sudo systemctl start systemd-networkd 设置开机自启 sudo systemctl enable systemd-networkd 检查状态&#xff08;确保显示 active (running)&#xff09; sudo systemctl status systemd-networkd 若想停止&#xff1a; 停止当前运行的服务 sud…

闸机控制系统从设计到实现全解析:第 4 篇:Redis 缓存与分布式锁实现

第 4 篇&#xff1a;Redis 缓存与分布式锁实现 一、Redis 在系统中的核心作用票证信息缓存&#xff1a;将高频访问的票证数据&#xff08;如状态、有效期&#xff09;缓存至 Redis&#xff0c;减少数据库查询&#xff0c;提升验证响应速度。分布式锁&#xff1a;在高并发场景下…

北京天津唐山廊坊沧州打捞日记

北京天津唐山廊坊沧州打捞日记 打捞搜蚯蚓疏通 北京&#xff1a;护城河畔的情谊打捞 清晨&#xff0c;北京的护城河在朝阳的映照下泛着微光。我接到一位年轻小伙的电话&#xff0c;声音中满是焦急。原来&#xff0c;他与女友在河边约会时&#xff0c;不小心将女友送他的定情玉佩…

全志刷机工具:PhoenixSuit-全志芯片处理器-刷机工具安装包及最详细使用教程指南

全志刷机工具&#xff1a;PhoenixSuit-全志芯片处理器刷机工具安装包及最详细使用教程指南&#xff0c;此文章主要是分享机顶盒、电视盒子&#xff0c;全志芯片盒子&#xff08;其中包含全志处理器、全志芯片、全志CPU等等&#xff09;的刷机工具、刷机工具安装教程以及如何使用…

浅谈 VM 桥接模式:让虚拟机像真实电脑一样接入网络

在虚拟化环境中&#xff0c;虚拟机&#xff08;Virtual Machine, VM&#xff09;与外部网络之间的通信方式有多种&#xff0c;比如 NAT 模式、Host-Only 模式、桥接模式&#xff08;Bridged Networking&#xff09; 等。其中&#xff0c;桥接模式是最接近“真实物理机”网络行为…

计算机视觉(1)-图像采集设备选型全景表(工业 + 医疗 + 车载)

图像采集设备选型全景表&#xff08;工业 医疗 车载&#xff09;一份面向工程师的“场景—设备—协议”速查表1 工业 & 医疗 & 通用场景应用场景主流设备形态接口 / 协议典型性能突出优势致命短板动态范围工业检测AOI / 量测 / 缺陷工业相机 采集卡Camera Link HSCo…

计算机视觉(3)深度学习模型部署平台技术选型与全栈实践指南

一、部署平台概述与分类 深度学习模型部署平台的分类需兼顾技术特性与应用场景的适配性&#xff0c;基于“技术定位-场景适配”双维度分类法&#xff0c;可将其划分为通用开源框架、云厂商服务及专用边缘工具三大类&#xff0c;各类别在设计目标、核心能力与场景覆盖上呈现显著…

Scratch编程:枪战游戏(附源码)

&#x1f3ae; 操作说明 W / A / S / D 或 方向键&#xff1a;移动 C&#xff1a;滑铲 空格键&#xff1a;取消滑铲 鼠标点击&#xff1a;开火 数字键 1 / 2 / 3 / 4&#xff1a;切换武器 G&#xff1a;快速使用道具 F&#xff1a;近战攻击 Q&#xff1a;瞄准 / 使用技能…

应急响应复现

一、前言&#xff1a;当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时&#xff0c;急需第一时间进行处理&#xff0c;使企业的网络信息系统在最短时间内恢复正常工作&#xff0c;进一步查找入侵来源&#xff0c;还原入侵事故过程&#xff0c;同时给出解决方案…

分布式事务Seata TCC模式篇

介绍 ​ 官网: https://seata.apache.org/zh-cn/docs/user/mode/tcc ​ 回顾Seata AT 模式基于 支持本地 ACID 事务 的 关系型数据库&#xff0c;如下&#xff1a; 一阶段 prepare 行为&#xff1a;在本地事务中&#xff0c;一并提交业务数据更新和相应回滚日志记录。二阶段 c…

Day37--动态规划--52. 携带研究材料(卡码网),518. 零钱兑换 II,377. 组合总和 Ⅳ,57. 爬楼梯(卡码网)

Day37–动态规划–52. 携带研究材料&#xff08;卡码网&#xff09;&#xff0c;518. 零钱兑换 II&#xff0c;377. 组合总和 Ⅳ&#xff0c;57. 爬楼梯&#xff08;卡码网&#xff09; 本文全部都是 ” 完全背包 “ 问题&#xff0c;从零到入坑&#xff0c;从入坑到爬出来。 本…

Linux文件操作

Linux文件Linux下的文件类型b 块设备文件---->存储类设备&#xff08;硬盘&#xff09;c 字符设备文件--->输入输出设备d 目录文件--->文件夹- 普通文件--> xxx.c xxx.h xxx.txt xxx.jpg xxx.mp4 a.outl 软链接文件-->快捷方式s 套接字文件-->网络通信p 管道…

Linux epoll 触发模式详解:LT vs ET

两种核心触发模式 1. 水平触发 (Level-Triggered, LT) 工作方式: 当文件描述符处于就绪状态时,epoll 会持续通知 只要状态未改变,每次调用 epoll_wait 都会返回该描述符 特点: c // 内核处理逻辑 (ep_send_events_proc) if (!(epi->event.events & EPOLLET)) { /…

STM32学习笔记6-TIM-2输出比较功能

第二部分&#xff0c;定时器的输出比较功能OC&#xff08;Output Compare&#xff09;输出比较输出比较可以通过比较CNT与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形每个高级定时器和通用定时器都拥有4…

MATLAB核心技巧:从入门到精通

一 1.数值 显示 格式 format style 设置 eg: pi format longE; or 2.清除指令 clc 清除命令行窗口 clear 清除工作区 cls 3.搜索路径设置 path(path,E:\ads\) or addpath 4.M文件 用户把要实现的命令写在一个以.m为扩展的文件中&#xff0c;然后由matlab系统进行解读…

AnyDesk远程工具免费版,v9.5.110绿色便携版,秒连远程桌面,剪贴板同步超实用

[软件名称]: AnyDesk远程工具免费版 [软件大小]: 7.5 MB [软件大小]: 夸克网盘 | 百度网盘 软件介绍 AnyDesk 让远程工作变得轻而易举。无论您身处办公室的另一端还是世界的另一侧&#xff0c;只需在设备上下载、安装并启动 AnyDesk.exe&#xff0c;即可轻松访问远程屏幕。…

AI: 给Gemini CLI配上“说明书”, 精通的GEMINI.md项目记忆

嘿&#xff0c;各位技术同好&#xff01;今天我们来聊一个能极大提升AI编程助手效率的酷炫功能——Google Gemini CLI 中的 GEMINI.md 文件。 在日常开发中&#xff0c;我们越来越依赖像 Gemini 这样的 AI 助手来帮我们写代码、调试 Bug 甚至重构项目。但大家是否遇到过这种情况…

[激光原理与应用-205]:光学器件 - LD与DFB的比较

一、相同点核心原理均基于半导体材料的受激辐射机制&#xff0c;通过电子-空穴复合产生光子。依赖谐振腔实现光反馈与放大&#xff0c;形成激光振荡。采用电泵浦方式驱动&#xff0c;电流注入激发载流子&#xff0c;实现粒子数反转。材料体系主要使用III-V族化合物半导体&#…

Cursor手机版:一半是神,一半是坑

大家好&#xff0c;我是羊仔&#xff0c;专注AI工具、智能体、编程。今天想和大家聊的这个工具&#xff0c;叫Cursor&#xff0c;可能很多朋友已经不陌生了&#xff0c;它作为一款AI原生代码编辑器&#xff0c;之前可谓是风光无两。但最近&#xff0c;它又搞了点新花样&#xf…