Go中无独立“指针数组”类型,常用[]T实现动态指针集合;指向数组的指针[N]T仅用于特殊场景如CGO;需注意对象生命周期、避免悬空指针及合理权衡性能。
在 Go 中,没有“指针数组”这种独立类型(如 C 那样固定长度的指针容器),但你可以用 指向数组的指针 或 元素为指针的切片 来实现类似效果。关键区别在于:Go 的切片本身是引用类型(包含底层数组指针、长度和容量),而“指针切片”([]*T)才是真正持有多个独立对象地址的集合。内存和引用管理的核心,在于理解谁拥有数据、何时分配/释放、以及如何避免悬空或泄漏。
[]*T 管理动态指针集合这是最常用也最符合 Go 习惯的方式——切片元素是 *T,每个元素可指向堆上独立分配的对象。
make([]*int, 0, n) 预分配空间,避免频繁扩容;追加用 append(s, &x),注意 &x 必须指向生命周期足够长的对象(比如堆分配或已声明的变量)for i := range data { s = append(s, &i) }),因为所有元素最终会指向同一个被反复覆盖的栈地址*s[i] = 42;替换指针本身:赋新地址 s[i] = &y
*[N]T 的适用场景这种类型表示“一个指向固定大小数组的指针”,不常用于集合管理,但在需要精确控制内存布局或对接 C ABI 时有用。
var p *[3]int;分配:p = new([3]int) 或 p = &[3]int{1,2,3}
(*p)[i];不能用 range 直接遍历指针,必须先解引用Go 自动管理堆内存,但指针集合仍需警惕逻辑层面的生命周期问题。
[]*T 中还有指针指向某个堆对象,该对象就仍被引用,不会被回收nil 或离开作用域),底层对象会在下次 GC 时回收不要为了“节省一个字节”而盲目用指针切片;权衡复制开销与间接访问成本。
type Point struct{ X,Y int })按值传递/存储通常更快,避免额外解引用和缓存未命中[]*T 更合理func process(vals []T))或自定义类型封装,减少指针暴露