Golang 数组基础

news2025/7/20 13:17:03

数组内部实现和基础功能

了解Go的数据结构,一般会从数组开始,因为数组是切片和映射的基础数据结构。

内部实现

在Go语言中,数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素连续块。数组的类型是固定统一的(也可以是结构类型)。

在这里插入图片描述

在内存中是连续分配的,由于内存连续,CPU能把正在使用的数据缓存更久的时间。而且内存连续很容易计算索引,可以快速迭代数组里的所有元素。
数组类型相同,且又连续分配,就可以以固定速度索引数组中的任意数据,速度非常快。
再来一个JavaScript的数组对比,谁快谁慢一目了然。
在这里插入图片描述

声明和初始化

声明数组需要指定内部存储的数据类型,以及需要存储元素的数量(也称为长度)。

var声明示例

// 声明一个包含了5个元素的int类型数组
var arr [5] int

一旦声明,数组里存储的数据类型和长度就都不能改变了。
作为一个经常写js的程序员,看到这里有点不淡定了,what ?不能更改了,想加第6个元素怎么办?
如果要存储更多的元素,就需要先创建一个更长的数组,再把原来的数组里面的值复制到新数组里。
在Go语言中声明变量时,总会使用对应类型的零值来对变量进行初始化。数组也一样,内部元素会使用对应类型的零值。

类型零值介绍:

类型零值
数值0
字符串空字符串
布尔false
指针nil
引用类型引用的底层数据结构对应的零值

快速创建数组并初始化

数组字面量声明

// 声明一个包含5个元素的整数数组
// 赋值并初始化
arr := [5] int{1,2,3,4,5}

自动计算声明数组的长度

// ...替代数组的长度
// 声明5个int类型的数组,容量由初始化值的数量决定
arr2 := [...] int {1,2,3,4,5}

声明数组并指定特定元素的值

// 声明一个有5个元素的值
// 指定其它中索引1和2的元素的值,其余为零值
arr3 := [5] int {1: 10, 2: 20}
// 输出结果: [0 10 20 0 0]

数组是值类型

Go 中的数组是值类型而不是引用类型。
意味着当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本。如果对新变量进行更改,则不会影响原始数组。
如果想引用传递,可以使用指针。

使用数组

访问和赋值

要访问数组里的元素,可以使用[index]索引来访问。

arr1 := [5] int {0,1,2,3,4}
// 修改索引2的值
arr1[2] = 100
// 输出结果:[0 1 100 3 4]

声明一个所有元素都是指针的数组,使用*运算符可以访问指针指向的值。

// 声明5个元素的指向整数的数组
// 整型指针初始化索引为0和1的数组元素
arr2 := [5] *int { 0: new(int), 1: new(int)}
//当前打印arr2: [0xc00001c098 0xc00001c0d0 <nil> <nil> <nil>]

//给索引0和1的元素赋值
*arr2[0] = 100
*arr2[1] = 200
// 再次打印arr2
fmt.Println(arr2)
// 打印结果:[0xc0000a6058 0xc0000a6090 <nil> <nil> <nil>]还是和赋值前一样,返回的是指针地址
fmt.Println(*arr2[0], *arr2[1])
// 打印指针结果:100, 200

同类型同长度的可以相互赋值

var arr4 [5]string
arr42 := [5]string{"a", "b", "c", "d", "e"}
arr4 = arr42
fmt.Println(arr4, arr42)
// 输出结果:[a b c d e] [a b c d e]    

指针数组复制,只会复制指针地址,而不会复制指针所指向的值,也就是说值变了,对应复制的数组值也会相应改变。

// 声明3个元素字符串的指针数组
var a1 [3]*string
// 声明第2个指针数组
a2 := [3]*string{new(string), new(string), new(string)}
// 给指针2数组赋值
*a2[0] = "apple"
*a2[1] = "huawei"
*a2[2] = "oppo"
// 打印对比指针数组,a1是nil
fmt.Println(a1, a2) // [<nil> <nil> <nil>] [0xc000104220 0xc000104230 0xc000104240]
a1 = a2
// a2赋给a1后,打印对比,指针地址一样
fmt.Println(a1, a2) // [0xc000040250 0xc000040260 0xc000040270] [0xc000040250 0xc000040260 0xc000040270]
// 改变*a2[0]的值 ,看看a1是否跟着变化
*a2[0] = "change apple"
// 指针地址没有变,但*a1[0]的实际值也跟着变化了
fmt.Println(*a1[0], *a2[0]) // change apple change apple

如图示:
改变*a1[0]的指针地址,0xc000040250地址处的赋值变更。
在这里插入图片描述

遍历数组元素

for循环遍历

代码示例:

a1 := [...]string{"apple", "huiwei", "oppo", "xiaomi"}
for i := 0; i <= len(a1); i++ {
	fmt.Printf("elem i %d:, value: %s", i, a1[i])
	fmt.Println()
}
range遍历

代码示例:

for i, v := range a1 {
		fmt.Printf("elem i %d, value :%s \n", i, v)
	}

输出结果与上面的for循环一致。

多维数组

数组本身只有一个维度,多维数组就是指多个数组组成创建多维数组。跟其它语言一样。
声明二维数组示例

// var 零值声明
var a1 [2][2]int
fmt.Println(a1)

// 字面量声明
a2 := [2][2]int{{1, 2}, {21, 22}}
fmt.Println(a2)

使用方法也类似,[index]索引访问和赋值使用。
多维数组复制也一样,需要相同的类型和相同的长度

数组在函数中的传递

在Go语言中,函数之间的变量传递都是以值的方式传递的。
如果变量是数组,意味着整个数组都会完整的复制传递给函数。
如果数组非常大,在值传递过程中会非常的消耗性能,不断的开辟内存空间来复制存储。
最佳的实现方式是使用指针传递。
示例:


// 指针传递函数
func arrShowValues2(arr *[1e6]int) {
	arr[0] = 201
	fmt.Println(arr[0])
}
func arrShowValues1(arr [1e6]int) {
	arr[0] = 101
	fmt.Println(arr[0])
}
func arrFn2() {
	// 100万个int类型的数据,分配8MB内存
	var arr1 [1e6]int
	// 值传递
	arrShowValues1(arr1) // 101
	// 指针传递
	arrShowValues2(&arr1)  // 201
}

// hello word
func main() {
	arrFn2()
}

两者的性能不在一个量级。

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

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

相关文章

Vue框架插槽(第八课)

案例 组件信息的通信 自己思考一下 答案在本文章的后面插槽 v-slot 这个时候我们就可以来定义插槽slot&#xff1a; 插槽的使用过程其实是抽取共性、预留不同&#xff1b;我们会将共同的元素、内容依然在组件内进行封装&#xff1b;同时会将不同的元素使用slot作为占位&#xf…

CTC 技术介绍概述——啃论文系列

CTC 技术介绍概述——啃论文系列 文章目录CTC 技术介绍概述——啃论文系列自我介绍摘要前言知识导图1. 定义2. 诞生背景2.1 频谱紧张例子&#xff0c;wifi的5GHz2.2 通信干扰——CTI2.3 管理困难2.4 异构通信传统实现——网关桥接2.5 CTC——异构直接通信3. 包级CTC3.1 基于RSS…

个人设计web前端大作业 基于html5制作美食菜谱网页设计作业代码

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

基于PHP+MySQL长途客用汽车票订票系统的设计与实现

随着时代的变迁汽车已经成为了人们日常生活中不可或缺的一部分,虽然很多人已经拥有了私家车,但是很多时候因为离家较远等原因,很多时候人们还是会通过客用汽车来进行一些出行,但是通常情况下客用车票都需要到客用站进行购买,这极其的不便利。 为了能够让用户足不出户就可以进行…

拿稳这24道JVM面试题,要价30k都有底气

1.什么是JVM? JVM 的全称是 「Java Virtual Machine」&#xff0c;也就是我们耳熟能详的 Java 虚拟机。它能识别 .class后缀的文件&#xff0c;并且能够解析它的指令&#xff0c;最终调用操作系统上的函数&#xff0c;完成我们想要的操作。 C开发出来的程序&#xff0c;编译…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.10 MongoDB 基础操作

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.10 MongoDB 基础操作4.10.1 MongoDB 基础操作4.10…

(3)paddle---近视眼睛分类的例子

1主要参考 &#xff08;0&#xff09;本教程和以下教程不够详细&#xff0c;还是推荐下面这个大佬的blog看一下 计算机视觉——眼疾图片识别&#xff08;数据集iChallenge-PM&#xff09;_「已注销」的博客-CSDN博客 &#xff08;1&#xff09;blibli视频 252-06_预测病理性…

Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

Vue2 与 Vue3 的区别 Vue3由于完全由TS进行重写&#xff0c;在应用中对类型判断的定义和使用有很强的表现。同一对象的多个键返回值必须通过定义对应的接口&#xff08;interface&#xff09;来进行类型定义。要不然在 ESLint 时都会报错。Vue2 与 Vue3 最大的区别: Vue2 使用…

jquery把页面<table>里的内容导出为后缀名为.xlsx的excel

1、问题描述 之前是用Blob把页面的<table>导出成.xls的Excel文件&#xff1a;Blob把html导出为excel文件_金斗潼关的博客-CSDN博客 不过由于微软的Excel对.xls扩展名的文件支持不是很好&#xff0c;打开会报一个警告 所以用户反馈说是不想弹出这个警告&#xff0c;要求…

【深度学习入门 2022 最新版】第一课 深度学习简介

【深度学习入门 2022 最新版】第一课 深度学习简介概述深度学习 vs 机器学习机器学习是什么深度学习是什么机器学习和深度学习的区别神经网络机器学习实现二分类神经网络实现二分类TensorFlowPyTorch神经网络的原理张量张量最小值 (补充)张量最大值 (补充)前向传播损失计算反向…

手撕AVL树

目录 一、概念 二、 结点的定义 2.1 键值对pair 2.2 定义细节 三、 AVL树的插入操作 3.1 平衡因子调整规则 3.2 旋转规则 3.2.1 新节点插入较高左子树的左侧 — 左左:右单旋 3.2.2 新节点插入较高右子树的右侧 — 右右:左单旋 3.2.3 新节点插入较高左子树的右侧 — …

论文管理系统(准备工作)

目录 一、项目需求响应图 二、准备工作 2.1创建一个Spring Initializr项目 2.2后端架构 2.2.1 controller层 2.2.2 entity层 2.2.3 interceptors层 2.2.4 mapper层 2.2.5 serivice层 2.2.6 main运行 2.2.7 mappers文件 2.3配置 application.yml文件 2.4加入依赖 一、项…

Postman如何携带token——Bearer Token和Headers

目录一、使用场景二、设置Bearer Token1.设置你的环境变量2.项目集合设置认证方式及环境变量3.登录接口的脚本三、通过脚本设置Headers1.登录请求设置环境变量2.设置集合的发送请求脚本一、使用场景 现在许多项目都使用jwt来实现用户登录和数据权限&#xff0c;校验过用户的用…

C++ Builder XE关于AdvStringGrid对EXCEL母表快速分表,并批量插入sheet子表简单操作

如何快速将ECXEL母表快速批量生成多个子表分表&#xff0c;并且在表中插入sheet子表的简单操作&#xff1a; //AdvStringGrid2->SaveToXLS(filename,false);//生成新EXCEL表格 //AdvStringGrid2->SaveToXLSSheet(filename,Fname);//插入sheet子表 //-----------------…

一篇五分生信临床模型预测文章代码复现——Figure 4-6 临床模型构建(五)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

XSS-labs靶场实战(五)——第12-14关

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是XSS-labs靶场实战第12-14关。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对…

认识和使用容器

目录 前言 一、容器化背后的发展历史和概念 1.容器的抽象 容器的比喻 2.计算机领域的容器 容器是一种标准化的软件单元 二、容器和微服务架构 1.容器的作用 快速搭建开发环境 将运行环境和配置放在代码中并部署 使用docker-compose来模拟生产环境 使用docker镜像进…

在JVM 中进程与线程关系、介绍线程:程序计数器、本地方法栈、虚拟机栈

首先,我们要了解进程和线程的基本概念 进程 process 一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的*.exe应用程序就是一个进程。 线程 thread 进程中的一个执行任务(控制单元),负责当前进…

vue-element-admin依赖报错npm ERR! code 128 npm ERR! An unknown git error occurred

解决vue-element-admin安装报错 npm ERR code 128 npm ERR An unknown git error occurred npm 报错截图&#xff1a; 参考地址 先试一下&#xff1a;控制台输入&#xff1a; git config --global http.sslverify “false” git config --global url.“https://”.insteadOf …

几行代码实现用Python输出表情包

近几日在搞邮件自动发送&#xff0c;发现python原来可以发小表情&#xff01;而且操作很容易&#xff0c;但是发现现在的博文介绍的不是很全面&#xff08;或者我没搜出来……&#xff09;&#xff0c;因此在此补充一二。 1. python输出的表情样子 图里的表情包当然才是冰山一角…