跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何在Golang中修改数组需要使用指针_Golang数组指针传递技巧

因为Go中数组是值类型,传参时会复制整个数组,函数内修改不影响原数组;需用数组指针(*[3]int)或切片([]int)才能修改原数据。 为什么直接传数组无法修改原数组 Go 语言中,
array
是值类型。当你把一个数组(比如
[3]int
)作为参数传给函数时,实际上传的是整个数组的副本。函数内部对它的任何修改,都不会影响调用方的原始数组。 常见错误现象:
func modify(arr [3]int) { arr[0] = 999 } a := [3]int{1, 2, 3} modify(a) // a 还是 [1 2 3],没变
这不是 bug,是 Go 的设计选择:数组大小固定、可比较、适合栈上分配。但这也意味着——想改原数组,必须绕过值拷贝。 用指针传递数组:明确指定长度和类型 最直接的方式是传指向数组的指针,比如
*[3]int
。这时函数接收的是地址,解引用后可直接写原内存。 必须写明数组长度(
[3]
),因为
[3]int
和
[4]int
是完全不同的类型 调用时需用
&a
取地址,不能漏掉
&
函数内通过
(*arr)[i]
或更常见的
arr[0]
(Go 允许对数组指针直接下标访问)操作 实操示例:
func modifyPtr(arr *[3]int) { arr[0] = 999 // 等价于 (*arr)[0] = 999 } a := [3]int{1, 2, 3} modifyPtr(&a) // a 现在是 [999 2 3]
更常用的是切片:隐式指针 + 灵活长度 绝大多数场景下,你真正需要的不是“修改固定长度数组”,而是“修改一段连续数据”。这时应优先用
[]int
(切片),它底层包含指向底层数组的指针、长度和容量。 立即学习 “ go语言免费学习笔记(深入) ”; 切片是引用类型(本质是结构体,含指针字段),传参时只拷贝这个小结构体,不影响语义上的“可修改原数据”。 函数签名更简洁:
func modifySlice(s []int)
,无需写死长度 调用方直接传
a[:]
(从数组转切片)或原生切片变量 注意:仅修改元素值可生效;但
append
可能导致底层数组扩容,此时原数组不受影响 示例:
a := [3]int{1, 2, 3} modifySlice(a[:]) // 传切片视图 // a 被修改了 func modifySlice(s []int) { if len(s) > 0 { s[0] = 999 // ✅ 影响原数组 } }
容易踩的坑:混淆数组指针和切片,以及越界行为 新手常把
*[3]int
当成“类似 C 的 int*”,结果发现不能用
len()
、不能遍历、甚至传错类型。
*[3]int
不是切片,不能直接用
range
,也不能调用
len()
或
cap()
—— 必须先解引用:
len(*arr)
误写成
func f(arr *[3]int)
却传
&[]int{1,2,3}
:类型不匹配,编译失败 用切片时以为
append
总是修改原数组:其实当容量不足时会分配新底层数组,原数组不变 数组指针在结构体字段中要小心:
type T struct { Data *[1024]byte }
会把整个 1KB 数组塞进结构体,通常应改用
[]byte
或
*[1024]byte
配合
make
分配 复杂点在于:Go 没有“动态数组”原生类型,数组和切片语义分离。选哪种,取决于你是否需要编译期长度检查、是否涉及 cgo、是否追求极致栈分配——大多数业务代码,用切片就够了,别硬套数组指针。

相关文章