<p>Go中数组传参是值传递,函数内修改不影响原数组;要修改需传数组指针* [N]T或改用切片[]T,因数组长度是类型组成部分,不同长度数组类型不兼容。</p>

数组传参后修改无效,是因为值传递
Go 中数组是值类型,func f(a [3]int) 接收的是整个数组的副本,函数内对 a[0] 的赋值不会影响调用方原始数组。这和 C 不同——C 里数组名传参会退化为指针,Go 则严格复制整块内存。
- 哪怕只改一个元素,也要拷贝全部数据;100 万个
int就拷贝 800KB - 不同长度的数组是不同类型:
[2]int和[3]int无法互相赋值或传参 - 编译器不会警告你“这个数组太大”,只会默默执行拷贝
想原地修改数组,必须传指针
用 *[N]T 类型参数,配合 &arr 调用,才能让函数真正操作原数组。注意解引用语法是 (*ptr)[i],不是 ptr[i](后者会报错)。
-
func modify(ptr *[3]int) { (*ptr)[0] = 42 }—— 必须加括号,否则运算符优先级出错 - 传
&arr时,arr类型必须严格匹配指针所指的数组长度,比如[3]int不能传给*[4]int - 如果只是读取数组内容,指针传递仍比值传递高效,尤其当数组 > 几十个元素时
切片传参更常用,但要注意 append 的副作用
多数场景下,应该用 []T 替代 [N]T 作为参数类型。切片本身是轻量结构体(含指针、len、cap),传参开销固定且很小,且能直接修改底层数组元素。
-
a[0] = 1在函数内生效,因为a和调用方切片共享同一底层数组 -
a = append(a, x)不会影响调用方切片——这是新分配的切片头,原变量未更新 - 若需扩容并让调用方感知变化,要么返回新切片,要么传
*[]T(不推荐,可读性差)
别混淆数组和切片的类型系统
Go 把数组长度纳入类型签名,导致 [5]int、[10]int、[]int 三者完全不兼容。写错一个数字,编译就失败,没有隐式转换。
立即学习“go语言免费学习笔记(深入)”;
- 函数参数写成
[5]int,就不能传make([]int, 5)得到的切片,哪怕长度刚好是 5 -
var a [3]int; f(a[:])可以把数组转成切片传入,但a[:]是新切片,底层数组仍是a - 泛型函数中若约束为
~[]T,它接受切片但拒绝数组;要支持数组得额外加约束如~[N]T


















