go数组是固定长度、值类型、内存连续的序列,长度属类型签名,[3]int与[5]int不可互赋;声明需指定长度,遍历时range的第二个值为元素副本,修改不影响原数组。

Go 语言中的数组是固定长度、值类型、内存连续的序列,声明后长度不可变——这是和切片最本质的区别,也是多数初学者混淆的起点。
数组声明必须指定长度,且长度是类型的一部分
Go 数组的长度是其类型签名的一部分,[3]int 和 [5]int 是完全不同的类型,不能互相赋值或传递给同一参数(除非用接口或反射)。
常见错误写法:
var a [3]int
a = [5]int{1,2,3,4,5} // 编译错误:cannot use [5]int literal as [3]int value正确声明方式包括:
立即学习“go语言免费学习笔记(深入)”;
-
var arr [4]int—— 声明并零值初始化 -
arr := [4]int{1, 2, 3, 4}—— 短变量声明,编译器推导长度 -
arr := [...]int{1, 2, 3, 4}—— 使用...让编译器自动计算长度(推荐用于字面量初始化)
遍历数组要用 for + range,但注意第二个返回值是副本
数组是值类型,range 遍历时第二个值(即元素)是数组元素的拷贝,修改它不会影响原数组:
arr := [3]int{1, 2, 3}
for i, v := range arr {
v = v * 10 // 这里改的是 v 的副本,arr[i] 不变
}
// arr 仍是 [1, 2, 3]如需修改原数组,必须通过索引:
- 用
for i := 0; i 显式索引访问 - 或用
for i := range arr(只取索引),再通过arr[i] = ...赋值
注意:range 对数组的迭代在编译期可能被优化为简单循环,性能无额外开销;但对大数组仍建议优先用索引方式避免意外拷贝语义。
传数组给函数会复制整个底层数组
因为数组是值类型,传参时会完整复制所有元素。例如 [1024]int 传参将拷贝 8KB(假设 int64),这在性能敏感场景不可接受。
实际开发中几乎总是该用切片替代:
- 函数签名应写
func process(arr []int)而非func process(arr [1024]int) - 调用时可直接传
arr[:]将数组转为切片(底层共享内存) - 若真需约束长度(如表示 IPv4 地址的
[4]byte),才保留数组类型,并接受其值拷贝成本
典型误用场景:把 [256]byte 作为缓冲区传入多次 IO 函数——应改为 []byte 并复用同一底层数组。
真正需要数组的场合其实很少:主要是固定长度的底层协议结构(如 SHA256 输出 [32]byte)、栈上小缓冲区、或作为结构体字段保证内存布局紧凑。其余情况,看到方括号就先想“是不是该用切片”。










