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

Go语言数组详解

摘要:本文参考菜鸟教程Go数组章节,从零讲解数组定义、初始化、遍历、传参特性,重点拆解入门头号误区:数组长度属于类型、数组是值类型、数组与切片的本质差异,配套完整可运行代码

一、Go数组核心定义

数组是长度固定、元素类型统一、内存连续的数据集合,用于存放一组相同类型的数据。
✅ 长度固定,数组创建完成之后,不能扩容、不能缩小;
长度是数组类型的一部分
[5]int[10]int是两种完全不同的数据类型,类型不匹配,无法赋值、传参、比较;
✅ 数组属于值类型。数组赋值、传入函数时会完整拷贝一份数据,修改副本不会影响原始数组。

拓展小知识:内存连续意味着数组支持通过索引快速随机访问,查询速度极快。

二、数组声明与五种初始化方式

2.1 基础语法

var数组名[数组长度]数据类型

示例:定义长度为5的int数组

vararr[5]int

2.2 五种初始化写法

方式1:仅声明,自动初始化为零值

Go不存在无默认值的数组,声明之后全部填充对应类型零值:int→0,string→"",bool→false,指针→nil。

packagemainimport"fmt"funcmain(){vararr[5]intfmt.Println(arr)// [0 0 0 0 0]}
方式2:完整初始化所有元素
// var标准写法vararr1[5]int=[5]int{1,2,3,4,5}// 短变量声明(开发常用)arr2:=[5]int{1,2,3,4,5}fmt.Println(arr1)fmt.Println(arr2)
方式3:使用...自动推导长度

不想手动填写数组长度,可以使用...,编译器自动统计元素个数确定数组长度。

arr:=[...]int{10,20,30,40}fmt.Println(len(arr))// 4

⚠️易错提醒:...只能用于数组,切片不能使用;多维数组仅最外层支持...,内层数组不允许。

方式4:指定下标局部初始化

只给指定索引赋值,其余位置自动填充零值。适合稀疏数组场景。

arr:=[5]int{1:666,3:888}fmt.Println(arr)// [0 666 0 888 0]
方式5:部分初始化,剩余补零

初始化元素数量少于数组长度,未赋值位置自动填充零值。

arr:=[5]int{1,2}fmt.Println(arr)// [1 2 0 0 0]

❌编译错误提醒:初始化元素总数不能大于数组定义长度,否则直接编译失败。

三、数组访问与遍历

3.1 通过索引访问元素

数组下标从0开始,合法区间:0 ~ len(arr)-1

funcmain(){arr:=[3]int{11,22,33}fmt.Println(arr[0])// 11fmt.Println(arr[2])// 33}

⚠️致命坑:索引越界不会出现编译警告,运行时直接触发panic,程序异常崩溃,编码时一定要注意边界!

3.2 两种遍历方式

  1. 普通for循环,依靠下标遍历
    适用场景:需要手动控制遍历起点、终点、步长
arr:=[3]int{100,200,300}fori:=0;i<len(arr);i++{fmt.Printf("下标:%d,值:%d\n",i,arr[i])}
  1. for range遍历(日常优先推荐)
    语法简洁,适合完整遍历整个数组
arr:=[3]int{100,200,300}// 同时接收下标与数值foridx,val:=rangearr{fmt.Println(idx,val)}// 不需要下标,使用空白标识符 _ 舍弃,避免变量未使用编译报错for_,val:=rangearr{fmt.Println(val)}

💡补充:range遍历数组时,每次循环得到的val是数组元素的拷贝,修改val无法改变原数组内容。

四、数组传参大坑:值类型拷贝

核心结论:数组是值类型,函数传参时会完整拷贝整个数组,修改副本无法影响原数组。

错误演示

packagemainimport"fmt"funcchangeArr(arr[3]int){arr[0]=999}funcmain(){arr:=[3]int{1,2,3}changeArr(arr)fmt.Println(arr)// [1 2 3],原值没有任何变化}

原理:传入函数内的只是原数组的拷贝,函数操作的是全新副本,和外部数组内存相互独立。

额外性能隐患:如果数组长度很大,完整拷贝会造成大量内存开销,严重影响性能!

两种可行解决方案

方案1:传递数组指针

传递数组地址,函数内部操作原始数组内存

funcchangeArr(arr*[3]int){arr[0]=999// Go语法糖,可以不用写(*arr)[0]}funcmain(){arr:=[3]int{1,2,3}changeArr(&arr)fmt.Println(arr)// [999 2 3]}

缺点:数组指针依旧绑定固定长度,通用性很差。

方案2:数组转为切片(项目开发首选)

开发中基本不会使用数组指针,更推荐把数组转为切片传递,摆脱固定长度限制。

funcchangeSlice(s[]int){s[0]=999}funcmain(){arr:=[3]int{1,2,3}changeSlice(arr[:])// arr[:] 将数组转为切片fmt.Println(arr)// [999 2 3]}

五、数组比较规则

Go数组支持==!=比较,但有严格限制:
只有长度相同、元素类型相同的两个数组才允许比较;
长度不一致直接触发编译错误,因为二者不属于同一种类型。

补充:数组不支持 > 、< 、>= 、<=大小比较!

funcmain(){a:=[2]int{1,2}b:=[2]int{1,2}c:=[3]int{1,2,3}fmt.Println(a==b)// true// fmt.Println(a == c) 编译报错,类型不一致}

六、多维数组拓展

实际开发偶尔会用到二维数组,简单示例:

packagemainimport"fmt"funcmain(){// 2行3列二维数组arr:=[2][3]int{{1,2,3},{4,5,6},}fmt.Println(arr[0][1])// 2}

重点:多维数组依然遵守规则,[2][3]int[3][2]int是两种不同类型。

七、数组 vs 切片核心对比

特性数组 [N]T切片 []T
长度固定不变,长度属于类型一部分长度动态,支持append扩容
类型兼容[5]int 和 [10]int 是不同类型同类型切片之间完全兼容
传参机制值传递,完整拷贝,大数据下性能差引用语义,共享底层数组,开销小
比较运算支持==、!=不支持直接使用==比较(nil除外)
开发场景极少使用,仅元素固定场景绝大多数业务场景首选

八、零基础高频易错点汇总

  1. [5]int[10]int属于不同类型,不能赋值、传参、比较;
  2. 数组是值类型,赋值、传参都会产生拷贝,修改副本不会影响原数组;
  3. 大数组直接传递性能低下,优先使用数组指针或者转为切片;
  4. 数组长度固定,无法动态扩容,业务开发优先选择切片;
  5. 数组索引越界不会编译报错,运行直接触发panic,程序崩溃;
  6. ...自动推导长度语法仅适用于数组,切片、多维数组内层不能使用;
  7. 数组初始化元素数量不能超过数组定义长度;
  8. 数组未赋值的元素,自动填充对应类型零值;
  9. range遍历数组,循环变量val是拷贝值,修改val无法更改原数组;
  10. 数组仅支持 == 和 !=,不能使用大于小于进行比较。

九、文末总结

  1. Go数组三大核心特点:定长、值类型、长度参与类型构成,一定要抛开其他语言数组的固有思维;
  2. 数组直接传参会发生完整拷贝,如果需要修改原始数据,推荐转为切片;
  3. 数组只适合元素数量固定不变的场景,真实项目99%场景使用切片;
  4. 数组是理解切片的基础,弄懂数组,后续学习切片会轻松很多。

参考资料:菜鸟教程 Go语言数组 https://www.runoob.com/go/go-arrays.html


http://www.jsqmd.com/news/1314609/

相关文章:

  • pi-subagents 完整部署指南:构建高效异步子代理系统的专业实战方案
  • VScode 智能插件安装
  • 安卓应用脱壳实战:反射大师原理、环境搭建与逆向分析
  • 基于树莓派的边缘控制器设计与实现:从原型到工业级应用
  • Stable Diffusion提示词权重调优秘技:用()与[]实现像素级控制,附可复用的12个权重模板
  • 2026年8月周口长途非急救转运解析:车辆、陪护与设备如何匹配 - 小校长
  • Arduino TFT触摸屏扩展板硬件解析与软件驱动实战
  • ADXL345加速度计实战:从I2C通信到数据滤波与姿态计算
  • 7B/13B模型微调显存爆炸?AMD GPU上这4招让我省下40%内存
  • muduo网络库(八):EventLoop 事件循环
  • UE5集成GDAL动态库实战:打通地理数据与虚幻引擎的桥梁
  • Wio Terminal SPI通信全解析:从原理到实战驱动屏幕与SD卡
  • Excel数据对比全攻略:从VLOOKUP到Power Query,高效核对两列数据
  • Meshroom:零代码实现专业级3D重建,让照片“活“起来
  • 应对气象大数据处理的挑战:MeteoInfo平台架构设计与工程实践深度解析
  • Go语言反射(Reflection)详解:原理、作用、TypeOf与ValueOf区别及常用函数
  • Windows 11终极优化指南:如何通过原生工具和脚本实现系统性能翻倍
  • 单片机毕业设计-基于 STM32F103 的多传感器智能调光台灯开发 基于多传感融合的人体感应护眼照明装置设计(018401)
  • 2026 年 8 月北京西城区钻戒变现实测,持证实体门店仪器专业验钻 - 生活时报
  • 2026 江苏 PCBA 打样转量产指南|研发打样、小批量试产、大批量量产衔接与优质厂商选型
  • C语言头文件与源文件关系详解:从编译原理到工程实践
  • 开源AI Markdown桌面应用:从部署到深度集成的全流程实践指南
  • 2026年8月鹅卵石滤料销售厂家推荐,园林鹅卵石/景观砾石/露营砾石/五彩鹅卵石/石英砂,鹅卵石滤料供应厂家推荐 - 品牌推荐师
  • Quorum 选型 AMD 方案入围后:我连夜补的 4 项技术债清单
  • MKS Monster8 8轴主板终极指南:从零开始配置你的3D打印机控制板
  • 3个痛点,一个方案:Slurm-web如何重塑HPC集群管理体验
  • 2026苏州托福培训机构全面测评|优选苏州爱特精英教育 - 产品评测官
  • ReachyMini桌面机器人开发指南:从SDK控制到多模态交互实战
  • PVZ创意工坊最高难度通关策略:从阵容搭配到微操技巧
  • 04数据结构