当前位置: 首页 > news >正文

深入探讨Go语言中的切片与数组操作

在编程世界中,数组一直是非常流行的数据结构,主要有两个原因:其一是简单易懂,其二是非常灵活,可以存储多种不同类型的数据。在Go语言中,数组的用法有其独特的特点,但与此同时,Go语言的切片(Slices)功能更为强大,能够在大多数情况下替代数组的使用。接下来,本文将深入探讨Go语言中的数组与切片的使用方法及其优缺点。

基础数组操作

数组在Go中是固定长度的结构,长度定义在数组类型之前。例如,我们可以声明一个存储四个整数的数组,如下所示:

anArray := [4]int{1, 2, 4, -4}

在这个例子中,数组的大小被定义为4,而它存储的类型为int。如果需要获取数组的长度,可以使用len()函数:

len(anArray) // 输出:4

数组的索引从0开始,因此第一个元素的索引为0,第二个元素的索引为1,以此类推。这意味着,对于一个长度为n的数组,合法的索引范围是0n-1

虽然在其他编程语言中我们通常使用for循环和数字变量来遍历数组,但在Go语言中,更常见的做法是使用range关键字。这不仅使代码更加简洁,还能避免手动使用len()函数来确定数组长度。下面是一个使用range遍历数组的例子:

for index, value := range anArray {fmt.Println(index, value)
}

在这个例子中,range会返回数组元素的索引和对应的值。

多维数组

在Go语言中,数组可以有多个维度,常见的二维数组和三维数组在某些场景下十分有用。下面是如何声明二维数组和三维数组的例子:

twoD := [4][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}
threeD := [2][2][2]int{{{1, 0}, {-2, 4}}, {{5, -1}, {7, 0}}}

我们可以通过嵌套for循环来访问多维数组中的所有元素。例如,遍历三维数组的代码如下:

for i := 0; i < len(threeD); i++ {for j := 0; j < len(threeD[i]); j++ {for k := 0; k < len(threeD[i][j]); k++ {fmt.Print(threeD[i][j][k], " ")}fmt.Println()}
}

在上面的代码中,我们使用三层嵌套的for循环来遍历三维数组的每一个元素。每一层循环对应数组的一维。也可以使用更加简洁的range关键字来完成相同的操作:

for _, v := range threeD {for _, m := range v {for _, s := range m {fmt.Print(s, " ")}fmt.Println()}
}

这个方法更加简洁,且代码更加清晰,但range不会提供循环的索引值。如果需要索引,则依然需要使用传统的for循环。

数组的局限性

尽管数组在某些场景下有其优势,但它也存在许多缺点。首先,数组的长度在定义时就被固定,无法动态扩展。这意味着如果数组没有足够的空间来存储新元素,就必须创建一个更大的数组,并将旧数组的元素复制过去。此外,数组作为函数参数传递时,传递的是数组的副本,函数内部的任何修改在函数外部都不会生效。

以下是一个简单的例子,展示数组传递给函数时的副本行为:

func modifyArray(arr [4]int) {arr[0] = 99
}func main() {anArray := [4]int{1, 2, 4, -4}modifyArray(anArray)fmt.Println(anArray) // 输出仍然是:[1 2 4 -4]
}

这段代码中,anArray传递给modifyArray函数时,函数中修改的仅仅是数组的副本,原始数组未受影响。

另外,由于数组的大小固定,在传递大数组时,创建副本会占用大量内存和处理时间,导致效率低下。为了解决这些问题,Go语言提供了切片(Slices)这一更灵活且高效的数据结构。

切片的强大之处

Go语言的切片功能非常强大,可以完全取代大多数情况下数组的使用。与数组不同,切片是动态的,可以根据需要自动扩展。当将切片传递给函数时,传递的是切片的引用,而不是副本,这意味着函数内部的修改在函数外部依然有效。例如:

func modifySlice(slc []int) {slc[0] = 99
}func main() {aSlice := []int{1, 2, 4, -4}modifySlice(aSlice)fmt.Println(aSlice) // 输出:[99 2 4 -4]
}

在这个例子中,modifySlice函数修改了切片的第一个元素,由于切片是按引用传递的,因此修改在函数外部生效。

此外,传递切片比传递数组更加高效,因为切片的底层实现是指向底层数组的指针,而不是整个数组的副本。因此,切片不仅更加灵活,还提高了性能,尤其在处理大数据时。

通过对Go语言数组和切片的深入探讨,我们可以看到数组虽然简单易用,但由于其固定长度和传递副本的限制,在大多数情况下并不适合复杂的应用场景。而切片的动态性和传递引用的特性,使其成为处理动态数据的首选工具。在实际开发中,数组的使用场景较少,而切片几乎可以完全取代数组,成为开发者日常使用的数据结构。

通过合理使用切片,开发者可以编写更加灵活和高效的Go代码。希望通过本文的介绍,大家对Go语言的数组与切片有了更清晰的理解,并能够在实际开发中灵活运用这些知识。

深入理解Go语言切片操作

在Go语言中,切片(slice)是非常强大且灵活的数据结构。相比数组,切片提供了更多的功能,并且能够动态扩展。在本文中,我们将探讨如何对切片进行基本操作、切片的特性及其应用。

创建与初始化切片

你可以通过以下方式创建一个切片:

aSliceLiteral := []int{1, 2, 3, 4, 5}

这种方式类似于数组的定义,但没有指定元素的数量。如果你在定义中指定了元素数量,那么就不是切片,而是数组。另一个创建切片的方法是使用make()函数,这种方法允许你创建指定长度和容量的空切片:

integer := make([]int, 20)

需要注意的是,Go会自动将切片的元素初始化为其类型的零值。比如整型切片的零值是0

切片的底层实际上是基于数组实现的,因此你可以通过索引访问其元素。例如,以下代码会输出切片中每个元素的值:

for i := 0; i < len(integer); i++ {fmt.Println(integer[i])
}

添加元素与重新切片

切片的大小可以动态增加。使用append()函数可以向切片添加元素,例如:

integer = append(integer, 12345)

你也可以通过索引访问切片的第一个和最后一个元素:

fmt.Println(integer[0])               // 访问第一个元素
fmt.Println(integer[len(integer)-1])  // 访问最后一个元素

切片的一个强大特性是可以使用[:]语法进行重新切片。下面的代码选取了切片中的第二个和第三个元素:

s2 := integer[1:3]

重新切片并不会创建切片的副本,而是引用相同的底层数组。因此,对重新切片的修改会影响原始切片:

s1 := make([]int, 5)
reSlice := s1[1:3]
reSlice[0] = -100
reSlice[1] = 123456
fmt.Println(s1)       // 输出:[0 -100 123456 0 0]
fmt.Println(reSlice)  // 输出:[-100 123456]

如上所示,修改reSlice中的元素实际上修改了s1中的元素,因为它们共享同一个底层数组。

切片的容量与自动扩展

切片有两个主要属性:长度和容量。长度表示切片当前元素的数量,而容量表示底层数组分配的空间。可以通过len()函数获取切片的长度,使用cap()函数获取其容量。切片的大小是动态扩展的,当空间不足时,Go会自动将容量翻倍。

下面是一个展示切片容量与长度变化的例子:

package main
import "fmt"func printSlice(x []int) {for _, number := range x {fmt.Print(number, " ")}fmt.Println()
}func main() {aSlice := []int{-1, 0, 4}printSlice(aSlice)fmt.Printf("容量: %d, 长度: %d\n", cap(aSlice), len(aSlice))aSlice = append(aSlice, -100)printSlice(aSlice)fmt.Printf("容量: %d, 长度: %d\n", cap(aSlice), len(aSlice))aSlice = append(aSlice, -2, -3, -4)printSlice(aSlice)fmt.Printf("容量: %d, 长度: %d\n", cap(aSlice), len(aSlice))
}

输出结果如下:

-1 0 4
容量: 3, 长度: 3
-1 0 4 -100
容量: 6, 长度: 4
-1 0 4 -100 -2 -3 -4
容量: 12, 长度: 7

你可以看到,当添加一个元素时,切片的长度增加,而容量则翻倍增长。

使用copy()函数复制切片

你可以使用copy()函数将一个切片的元素复制到另一个切片中。copy(dst, src)会将src切片中的元素复制到dst,并且只复制dstsrc中较短的部分。例如:

a6 := []int{-10, 1, 2, 3, 4, 5}
a4 := []int{-1, -2, -3, -4}
copy(a6, a4)
fmt.Println(a6) // 输出:[-1 -2 -3 -4 4 5]

在这个例子中,a4的所有元素都被复制到a6,但a6的最后两个元素保持不变。

多维切片

切片不仅可以是一维的,还可以是多维的。例如,下面的代码创建了一个二维切片:

s1 := make([][]int, 4)

多维切片的元素也是切片,因此可以通过append()函数来初始化和扩展:

for i := 0; i < len(s1); i++ {for j := 0; j < 2; j++ {s1[i] = append(s1[i], i*j)}
}

使用sort.Slice()排序切片

Go提供了一个强大的sort.Slice()函数,用于根据指定的条件对切片进行排序。如下是一个简单的例子:

package main
import ("fmt""sort"
)type Person struct {name   stringheight int
}func main() {people := []Person{{"张三", 180},{"李四", 175},{"王五", 160},}sort.Slice(people, func(i, j int) bool {return people[i].height < people[j].height})fmt.Println("升序:", people)sort.Slice(people, func(i, j int) bool {return people[i].height > people[j].height})fmt.Println("降序:", people)
}

运行结果:

升序: [{王五 160} {李四 175} {张三 180}]
降序: [{张三 180} {李四 175} {王五 160}]

总结

Go语言中的切片功能非常强大。它们不仅灵活且动态扩展,还可以通过append()copy()等函数进行各种操作。切片比数组更适合大多数应用场景,尤其在处理动态数据时。通过掌握切片的这些特性,开发者可以编写出更高效、更灵活的Go语言程序。

相关文章:

深入探讨Go语言中的切片与数组操作

在编程世界中&#xff0c;数组一直是非常流行的数据结构&#xff0c;主要有两个原因&#xff1a;其一是简单易懂&#xff0c;其二是非常灵活&#xff0c;可以存储多种不同类型的数据。在Go语言中&#xff0c;数组的用法有其独特的特点&#xff0c;但与此同时&#xff0c;Go语言…...

【WPS Excel】复制表格时,提示“图片太大,超过部份将被截去“ 问题

WPS表格 2019版本 升级到 WPS最新版 WPS-支持多人在线协作编辑Word、Excel和PPT文档_WPS官方网站 使用最新版就能够解决这个问题&#xff0c;如果仍旧无法解决可以勾选如下配置 重启Excel解决。 请勾选&#xff1a;文件 - 选项 - 编辑 - 不提示且不压缩文件中的图像...

驱动(RK3588S)第九课时:多节点驱动与函数接口

目录 一、多节点概念1、所用到的结构体说明2、函数接口主要是read和write函数2.1、把应用层的数据拷贝给底层2.2、把应用层的数据拷贝给底层 3、应用层的read和write函数4、底层的read和write函数二、ioctl控制命令接口1、概念2、函数介绍应用层和驱动层 三、代码与现象1.编写L…...

Linux系统下配置MySQL

1. 寻找MySQL的配置文件 MySQL的配置文件通常位于以下位置&#xff1a; 在大多数Linux系统上&#xff0c;主配置文件通常位于/etc/mysql/my.cnf或/etc/my.cnf。在macOS上&#xff0c;如果你使用Homebrew安装MySQL&#xff0c;配置文件通常位于/usr/local/etc/my.cnf。在Window…...

信捷 XD PLC POU编程之FB

在使用信捷的POU方式编程&#xff0c;可以建立两种POU:FB和FC。 FB和FC这两种POU又各自可以建立梯形图语言POU和C语言POU。 函数块&#xff08;FB&#xff09;是把反复使用的部分程序块转换成一种通用部件&#xff0c;他可以在程序中反复被调用&#xff0c;不仅 提高了程序的开…...

终于有人把云计算、大数据和人工智能讲明白了!

引言 在当今数字化时代&#xff0c;云计算、大数据和人工智能成为了全球科技界的热门话题。这些技术的迅猛发展以及应用范围的不断扩大&#xff0c;正深刻地改变着我们的生活和工作方式。云计算为我们提供了有效的计算和存储能力&#xff0c;大数据则以海量的信息资源为基础&a…...

【编程底层思考】详解Java内存模型(JMM)原理及其作用

Java内存模型&#xff08;Java Memory Model, JMM&#xff09;是Java虚拟机&#xff08;JVM&#xff09;的一个核心概念&#xff0c;它定义了Java程序中各种变量&#xff08;线程共享变量&#xff09;的访问规则&#xff0c;以及在并发环境下&#xff0c;为了确保数据的可见性、…...

Docker的基本概念和优势

Docker是一个开源的容器化平台&#xff0c;它可以将应用程序及其所有依赖项和运行环境打包到一个称为容器的独立单元中。容器化使得应用程序在不同的环境中可以以相同的方式运行&#xff0c;并且更加轻量级和可移植。 Docker的基本概念包括以下几点&#xff1a; 镜像&#xf…...

数据结构————内核链表

内核链表是Linux内核中广泛使用的一种数据结构&#xff0c;它具有以下特点&#xff1a; 1.双向循环链表&#xff1a;每个节点包含两个指针&#xff0c;一个指向前驱节点&#xff08;prev&#xff09;&#xff0c;另一个指向后继节点&#xff08;next&#xff09;&#xff0c;…...

使用API接口获取某宝商品数据详情

什么是淘宝API接口&#xff1f; 淘宝API接口是淘宝开放平台为开发者提供的一种应用程序接口。它允许开发者通过编程方式&#xff0c;安全、高效地与淘宝平台进行数据交互&#xff0c;从而获取商品详细信息、用户信息、订单信息等多种数据。这些接口不仅简化了数据获取流程&…...

用Python实现时间序列模型实战——Day 15: 时间序列模型的选择与组合

一、学习内容 1. 模型选择的标准与方法&#xff08;如 AIC、BIC&#xff09; 在时间序列建模中&#xff0c;模型的选择是非常重要的&#xff0c;常用的模型选择标准包括 AIC (Akaike Information Criterion) 和 BIC (Bayesian Information Criterion)。 AIC (Akaike Informat…...

大数据之Flink(五)

15、Flink SQL 15.1、sql-client准备 启用Hadoop集群(在Hadoop100上) start-all.sh启用yarn-session模式 /export/soft/flink-1.13.0/bin/yarn-session.sh -d启动sql-client bin/sql-client.sh embedded -s yarn-sessionsql文件初始化 可以初始化模式、环境&#xff08;流/批…...

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型&#xff0c;它综合考虑了土壤-水分-大气以及植被间的相互作用&#xff1b;是一种描述作物生长过程的一种机理性作物生长模型。它不但…...

基于 jenkins 的持续测试方案

CI/CD Continuous Integration; Continuous Deployment; 持续集成&#xff0c;将新代码和旧代码一起打包、构建&#xff1b;持续部署&#xff0c;将新构建的包进行部署&#xff1b;持续测试&#xff0c;将新代码、新单元测试一起测试&#xff1b;方案&#xff1a; 公有云DevO…...

我算见识到算法岗transformer面试的难度了

在面试算法岗的时候看到了这篇Transformer面试题&#xff0c;作者梳理一些关于Transformer的知识点&#xff0c;还会陆续更新最新的面试题和讲解答案&#xff01; 也算是见识到了transformer的面试难度了 1.Transformer为何使用多头注意力机制?(为什么不使用一个头) 2.Tra…...

CommonCollections1

CommonCollections1链 CommonCollections1poc展示调用链分析AbstractInputCheckedMapDecoratorTransformedMapChainedTransformerConstantTransformerInvokerTransformer poc分析通过反射实现Runtime.getRuntime().exec("calc.exe")forNamegetMethodinvoke 依据反射构…...

6、关于Medical-Transformer

6、关于Medical-Transformer Axial-Attention原文链接&#xff1a;Axial-attention Medical-Transformer原文链接&#xff1a;Medical-Transformer Medical-Transformer实际上是Axial-Attention在医学领域的运行&#xff0c;只是在这基础上增加了门机制&#xff0c;实际上也就…...

19_单片机开发常用工具的使用

工欲善其事必先利其器&#xff0c;我们做单片机开发的时候&#xff0c;不管是调试电路还是调试程序&#xff0c;都需要借助一些辅助工具来帮助查找和定位问题&#xff0c;从而帮助我们顺利解决问题。没有任何辅助工具的单片机项目开发很可能就是无法完成的任务&#xff0c;不过…...

最新版微服务项目搭建

一&#xff0c;项目总体介绍 在本项目中&#xff0c;我将使用alibabba的 nacos 作为项目的注册中心&#xff0c;使用 spring cloud gateway 做为项目的网关&#xff0c;用 openfeign 作为服务间的调用组件。 项目总体架构图如下&#xff1a; 注意&#xff1a;我的Java环境是17…...

spring揭秘19-spring事务01-事务抽象

文章目录 【README】【1】事务基本元素【1.1】事务分类 【2】java事务管理【2.1】基于java的局部事务管理【2.2】基于java的分布式事务管理【2.2.1】基于JTA的分布式事务管理【2.2.2】基于JCA的分布式事务管理 【2.3】java事务管理的问题 【3】spring事务抽象概述【3.1】spring…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...