一篇文章让你明白Go语言之切片的概念和用法

Go语言的切片(slice)是一个灵活且强大的数据结构。相比数组,切片的长度可以动态变化,更适合用于处理动态数据。切片是基于数组构建的抽象,为开发者提供了更高效的内存管理和数据操作手段。

一、切片的概念和结构

切片其实是对底层数组的一个引用。它包含三个核心信息:

  1. 指向底层数组的指针(Pointer) - 指向切片的第一个元素(在底层数组中的位置)。
  2. 切片的长度(Length) - 当前切片中实际包含的元素数。
  3. 切片的容量(Capacity) - 从切片的起始位置到底层数组末尾的元素总数。

切片在Go语言中被设计为动态扩展的数据结构,通过共享底层数组实现快速操作和高效的内存管理。

二、切片的创建方式

切片有多种创建方式,具体如下:

1. 从数组创建切片

arr := [5]int{10, 20, 30, 40, 50}
s := arr[1:4]  // 从arr数组的第1到第3个元素创建一个切片
fmt.Println(s) // 输出:[20 30 40]

在上例中,arr[1:4]的含义是从数组的索引1(包含)到索引4(不包含)生成一个切片。切片len(s)为3,cap(s)为4。

2. 通过make函数创建切片

make函数可以创建一个指定长度和容量的切片。其格式为:make([]Type, length, capacity)

s := make([]int, 3, 5) // 创建一个长度为3,容量为5的切片
fmt.Println(s)         // 输出:[0 0 0]
fmt.Println(len(s))    // 输出:3
fmt.Println(cap(s))    // 输出:5

如果省略容量参数,则容量和长度相同。

3. 直接使用字面量创建切片

s := []int{1, 2, 3} // 创建一个包含元素1, 2, 3的切片,长度和容量都为3
fmt.Println(s)      // 输出:[1 2 3]

三、切片的属性

通过内置函数lencap可以分别获取切片的长度和容量。

s := []int{1, 2, 3, 4, 5}
fmt.Println("长度:", len(s)) // 输出:5
fmt.Println("容量:", cap(s)) // 输出:5

当我们基于一个切片或数组进行“切片操作”时,容量会从新的切片起始位置算起,到底层数组的末尾。

四、切片的常用操作

1. 切片的追加操作(append)

append是一个用于向切片追加元素的内置函数。若切片容量不足时,append会创建一个新的底层数组,将旧数据复制过去,然后再追加新元素。

s := []int{1, 2, 3}
s = append(s, 4, 5)   // 追加元素4, 5
fmt.Println(s)        // 输出:[1 2 3 4 5]
fmt.Println(len(s))   // 输出:5
fmt.Println(cap(s))   // 如果之前容量为3,现在可能变成6

2. 切片的切片(子切片)

切片也可以再次“切片”,生成一个新的子切片。子切片共享原切片的底层数组,因此对数据的更改会影响彼此。

s := []int{1, 2, 3, 4, 5}
sub := s[1:4]  // 创建从索引1到索引3的子切片
fmt.Println(sub)  // 输出:[2 3 4]sub[0] = 20      // 修改sub的第一个元素
fmt.Println(s)   // 输出:[1 20 3 4 5],s也被修改

五、切片的扩容机制

切片的底层数组容量是有限的,如果超出容量,Go语言会自动扩容。扩容时,Go会创建一个新的、较大的底层数组,并将旧数组的数据拷贝到新数组中。扩容的策略通常是成倍扩展容量,但并不保证每次都是相同倍数。

例如,当容量不够时,以下代码展示了扩容的现象:

s := make([]int, 2, 2)
s[0] = 1
s[1] = 2
fmt.Println(len(s), cap(s))  // 输出:2 2s = append(s, 3)            // 追加一个元素
fmt.Println(len(s), cap(s))  // 输出:3 4,容量翻倍

在上例中,append使切片的容量从2变为4。

六、切片的拷贝(copy函数)

copy函数用于将一个切片的内容复制到另一个切片中,格式为:copy(dst, src)。它会根据目标切片的长度,复制最多与dst长度相同的元素数。

src := []int{1, 2, 3}
dst := make([]int, 2)
copy(dst, src)  // 只会复制src的前两个元素到dst中
fmt.Println(dst)  // 输出:[1 2]

七、切片是引用类型的注意事项

切片是引用类型,因此多个切片可能共享同一个底层数组。这种情况下,一个切片的修改可能会影响另一个切片的内容。为了避免这种问题,可以在切片上创建一个副本。

original := []int{1, 2, 3}
copySlice := make([]int, len(original))
copy(copySlice, original) // 将original内容复制到copySlice
copySlice[0] = 100
fmt.Println(original)  // 输出:[1 2 3]
fmt.Println(copySlice) // 输出:[100 2 3]

八、示例代码总结

以下代码展示了切片的创建、追加、切片操作和拷贝:

package main
import "fmt"func main() {// 基于数组创建切片arr := [5]int{1, 2, 3, 4, 5}s := arr[1:4]fmt.Println("切片内容:", s)fmt.Println("切片长度:", len(s))fmt.Println("切片容量:", cap(s))// 追加元素s = append(s, 6)fmt.Println("追加后切片:", s)// 创建切片副本copySlice := make([]int, len(s))copy(copySlice, s)fmt.Println("副本切片:", copySlice)// 子切片修改影响原切片subSlice := s[1:3]subSlice[0] = 100fmt.Println("修改子切片后,原切片:", s)
}

以上代码展示了创建切片、追加元素、复制切片,以及子切片修改对原切片的影响等操作。

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

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

相关文章

css background-image背景图片轮播

1、CSS背景样式有以下几种: 背景颜色(background-color):设置元素的背景颜色。背景图片(background-image):设置元素的背景图片。背景重复(background-repeat)&#xff…

第八篇: 通过使用Google BigQuery进行数据批量和自动化处理

使用Python进行Google BigQuery数据批量和自动化处理 在大数据分析的日常工作中,定期更新、查询和处理数据是一项必不可少的任务。Google BigQuery结合Python脚本,可大幅简化这一过程。本文将介绍如何通过Python自动查询和更新BigQuery中的降水量数据&a…

WPF+MVVM案例实战与特效(二十八)- 自定义WPF ComboBox样式:打造个性化下拉菜单

文章目录 1. 引言案例效果3. ComboBox 基础4. 自定义 ComboBox 样式4.1 定义 ComboBox 样式4.2 定义 ComboBoxItem 样式4.3 定义 ToggleButton 样式4.4 定义 Popup 样式5. 示例代码6. 结论1. 引言 在WPF应用程序中,ComboBox控件是一个常用的输入控件,用于从多个选项中选择一…

7.《双指针篇》---⑦三数之和(中等偏难)

题目传送门 方法一:双指针 1.新建一个顺序表用来返回结果。并排序数组。 2.for循环 i 从第一个数组元素遍历到倒数第三个数。 3.如果遍历过程中有值大于0的则break; 4.定义左右指针,以及target。int left i 1, right n - 1; int target -nums[i];…

Linux的Shell脚本1

shell启动流程 脚本启动时的home配置文件Linux是: 登录 shell 会话的启动文件 文件 内容 /etc/profile 应用于所有用户的全局配置脚本。 ~/.bash_profile 用户私人的启动文件。可以用来扩展或重写全局配置脚本中的设置。 ~/.bash_login 如果文件 ~/.bash_profi…

k8s 处理namespace删除一直处于Terminating —— 筑梦之路

问题现象 k8s集群要清理某个名空间,把该名空间下的资源全部删除后,删除名空间,一直处于Terminating状态,无法完全清理掉。 如何处理 为什么要记录下这个处理的步骤,经过查询资料,网上也有各种各样的方法&…

Spring Boot应用开发:从入门到精通

Spring Boot应用开发:从入门到精通 Spring Boot是Spring框架的一个子项目,旨在简化Spring应用的初始搭建和开发过程。通过自动配置和约定大于配置的原则,Spring Boot使开发者能够快速构建独立的、生产级别的Spring应用。本文将深入探讨Sprin…

CSS实现文字渐变效果

效果图: 代码: h1 {font-size: 100px;color:linear-gradient(gold,deeppink);background-image:linear-gradient( -gold, deeppink); /*春意盎然*///背景被裁剪成文字的前景色。background-clip:text;/*兼容内核版本较低的浏览器*/-webkit-background-c…

ai外呼机器人的作用有哪些?

ai外呼机器人具有极高的工作效率。日拨打成千上万通不是问题,同时,机器人还可以快速筛选潜在客户,将更多精力集中在有价值的客户身上,进一步提升营销效果。183-3601-7550 ai外呼机器人的作用: 1、搭建系统&#xff0c…

【LeetCode】【算法】236. 二叉树最近公共祖先

LeetCode 236. 二叉树最近公共祖先 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 思路 思路:后序遍历(左右中),如果在左/右侧树上找到了该节点则返回对应节点,其公共节点就为中,否…

大厂面试真题-说说redis的分片方式

Redis的分片机制是其实现数据分布式存储和处理的关键,它允许将数据拆分存放在不同的Redis实例上,每个Redis实例只包含所有键的子集,从而提高了系统的性能和可扩展性。以下是Redis常用的分片方式: 一、按照范围分片 这种方式相对…

DOM操作和事件监听综合练习——轮播图

下面制作一个如下图所示的轮播图&#xff08;按Enter键可以控制轮播的开启和关闭&#xff0c;或者点击按钮“第几张”即可跳转到第几张&#xff09;&#xff1a; 下面是其HTML和CSS代码&#xff08;还没有设置轮播&#xff09;&#xff1a; <!DOCTYPE html> <html …

[全网最细数据结构完整版]第七篇:3分钟带你吃透队列

目录 1->队列的概念及结构 2->队列的实现 2.1定义队列基本结构 struct QueueNode 和 struct Queue 2.2队列初始化函数 QueueInit 函数 2.3队列销毁函数 QueueDestroy 函数 2.4队列插入数据函数 QueuePush 函数 2.5判断队列是否为空,空返回true,非空返回false 2.6队列删…

力扣动态规划基础版(矩阵型)

62.不同路径&#xff08;唯一路径问题&#xff09; 62. 不同路径https://leetcode.cn/problems/unique-paths/ 方法一&#xff1a;动态规划 找状态转移方程&#xff0c;也就是说它从左上角走到右下角&#xff0c;只能往右或者往下走&#xff0c;那么设置一个位置为&#xff…

Hive 实现查询用户连续三天登录记录

标题&#xff1a;Hive 实现查询用户连续三天登录记录 在数据分析和处理中&#xff0c;经常会遇到需要查询特定条件数据的情况。本文将介绍如何使用 Hive 来查询用户连续三天登录的所有数据记录。 一、问题背景 我们有一个用户登录记录表&#xff0c;其中包含用户的登录日期信…

算法(第一周)

一周周五&#xff0c;总结一下本周的算法学习&#xff0c;从本周开始重新学习许久未见的算法&#xff0c;当然不同于大一时使用的 C 语言以及做过的简单题&#xff0c;现在是每天一题 C 和 JavaScript&#xff08;还在学&#xff0c;目前只写了一题&#xff09; 题单是代码随想…

08 反射与注解

目录 1.Java类加载机制 类加载器 双亲委派模型 工作流程 优点 2.反射 基本概念 常见用法 1. 获取 Class 对象 2.获取构造方法 3.获取成员方法 4.获取成员变量 3.注解 注解的基本概念 定义和使用注解 定义注解 使用注解 解释 元注解详解 常见内置注解 总结…

【Linux第八课-进程间通信】管道、共享内存、消息队列、信号量、信号、可重入函数、volatile

目录 进程间通信为什么&#xff1f;是什么&#xff1f;怎么办&#xff1f;一般规律具体做法 匿名管道原理代码 命名管道原理代码 system V共享内存消息队列信号量信号量的接口 信号概念为什么&#xff1f;怎么办&#xff1f;准备信号的产生信号的保存概念三张表匹配的操作和系统…

Android 应用插件化及其进程关系梳理

插件应用的AndroidManifest.xml <manifest xmlns:android"http://schemas.android.com/apk/res/android"coreApp"true"package"com.demo.phone"android:sharedUserId"android.uid.phone"><uses-sdk android:minSdkVersion&q…

C# 集合与泛型

文章目录 前言1.什么是集合&#xff1f;2.非泛型集合&#xff08;了解即可&#xff09;2.1常见的非泛型集合 3.泛型的概念4.常用的泛型集合4.1 List < T > <T> <T>4.2 Dictionary<TKey, TValue>4.3 Queue < T > <T> <T>4.4 S t a c…