go中数组是值类型,传参时复制整个数组,无法修改原数组;需用指针*[n]t传参并解引用修改,或改用切片[]t。

为什么直接传数组无法修改原数组元素
Go 语言中数组是值类型,函数调用时会复制整个数组。哪怕你在函数内对 arr[i] 赋值,改的也只是副本,原数组完全不受影响。这是新手最常踩的坑——误以为和 C 或 Python 列表一样可直接修改。
验证方式很简单:写个函数尝试改第 0 个元素,调用后打印原数组,你会发现它没变。
用指针传数组的正确写法
必须传递指向数组的指针,即类型为 *[N]T(比如 *[3]int),而不是 []T(切片)或 [N]T(数组值)。只有这样,函数内通过 *ptr 解引用才能定位到原始内存位置。
- 声明函数参数为
func modify(ptr *[3]int),不是func modify(arr [3]int) - 调用时传地址:
modify(&myArray),漏掉&就又变成传值了 - 函数内修改需先解引用:
(*ptr)[0] = 42,不能写成ptr[0] = 42(这会报错:cannot assign to ptr[0])
数组指针 vs 切片:什么时候该用哪个
如果你只关心“修改元素”,切片([]int)通常更简单——它底层包含指向底层数组的指针,传参即自带可修改性,无需显式取址/解引用。但切片长度可变,而数组长度固定;若逻辑强依赖数组长度(如固定大小缓冲区、与 C 互操作),就必须用 *[N]T。
性能上无实质差异,但切片更符合 Go 习惯;硬用数组指针容易写错解引用语法,且泛型适配稍麻烦([N]T 中 N 是类型一部分,不能参数化)。
常见错误和调试提示
典型错误信息包括:cannot use &arr as *[3]int value in argument to modify: *[]int is not *[3]int(把切片地址当数组指针传)、invalid operation: cannot assign to ptr[0](忘了加 * 解引用)。
- 检查变量声明:确认你定义的是
var arr [3]int,不是var arr []int - 检查函数签名:参数类型必须严格匹配数组长度和元素类型,
*[3]int和*[4]int是不同类型 - 调试时打印地址:
fmt.Printf("%p", &arr)和在函数内打印fmt.Printf("%p", ptr),两者应一致
数组指针的语法约束比切片紧得多,稍不注意就编译失败——这不是设计缺陷,而是 Go 在强制你明确区分“固定布局”和“动态视图”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











