Go中声明初始化指向数组元素的指针需用循环逐个取地址存入[]T切片,如ptrs[i] = &arr[i];直接修改ptrs[i]可更新原数组元素,但须确保指针生命周期内原数据未销毁。
Go 里没有“指针数组”这种类型(即 []*int 是指针切片,不是 C 风格的指针数组),但你可以获取数组中每个元素的地址并存入一个指针切片。关键点是:数组本身是值类型,&arr[i] 得到的是第 i 个元素的地址,类型为 *int。
常见错误是试图对整个数组取地址后做偏移(如 &arr + i),Go 不支持指针算术,也不允许对数组变量直接做算术运算。
[]*T 切片len(arr) 可安全用于循环边界arr := [3]int{10, 20, 30}
ptrs := make([]*int, len(arr))
for i := range arr {
ptrs[i] = &arr[i]
}
// ptrs[0] 现在指向 arr[0],修改 *ptrs[0] 会改变 arr[0]是的,只要指针指向的是原数组的元素地址,解引用并赋值就直接修改原位置。这是 Go 指针最基础也最可靠的用途——绕过值拷贝,实现就地更新。
容易踩的坑在于混淆“指针副本”和“被指向对象”。比如把 ptrs[i] 赋给另一个变量 p := ptrs[i],p 是新指针变量,但它仍指向同一地址,*p = 999 依然改的是原数组元素。
立即学习“go语言免费学习笔记(深入)”;
*ptrs[i] = newValue
ptrs[i] = &newValue——这会让该指针指向一个新局部变量,原数组不受影响func f(a [3]int)),那 &a[i] 指向的是副本,修改无效;必须传指针 *[3]int 或用切片切片底层有底层数组,slice[i] 的地址仍是底层数组对应元素的地址,所以 &slice[i] 依然可用、可修改原数据。但要注意切片头可能被重新切(slice = slice[1:]),此时旧指针仍指向原底层数组位置,不一定再属于当前切片范围——Go 不检查越界解引用,运行时可能读到脏数据或引发 panic(取决于 GC 和内存状态)。
make([]int, n) 后不再 append)data := make([]int, 3)
for i := range data {
data[i] = i * 10
}
ptrs := make([]*int, len(data))
for i := range data {
ptrs[i] = &data[i] // 这里 &data[i] 有效,指向底层数组
}
*ptrs[1] = 999 // data[1] 变成 999**int 来批量操作有人想定义 pp := &ptrs(即 **int),再通过 **pp 改值,这是误解。Go 中 **int 是“指向 int 指针的指针”,它只能间接修改一个指针变量本身的值(比如让那个指针指向别处),不能用来遍历或批量解引用。
真正需要批量修改时,还是得遍历 []*int,逐个 *p = x。没有语法糖能跳过这一步。
pp := &ptrs[0] 是 **int,*pp 是 *int,**pp 是 int —— 它只关联单个元素[]*T 并解引用是标准做法,现代 CPU 对 cache 友好,无需过度优化实际用的时候,最常漏掉的是生命周期检查:传进来的数组或切片是不是临时的?指针存下来之后,原数据还在不在?这点比语法更关键。