Go中声明指针数组的正确语法是[N]T,表示长度为N、元素类型为T的数组;修饰元素类型,而非整个数组,[N]T与[N]T、[]T语义完全不同。

Go里声明指针数组的语法是 [N]*T
不是 *[N]T,也不是 []*T(那是切片),更不是 *[]T。Go 的数组类型中,* 修饰的是元素类型,所以 [3]*int 表示“长度为 3 的数组,每个元素都是 *int 类型”。
常见错误是把 C 风格写法照搬过来,比如写成 *[3]int —— 这在 Go 中是“指向长度为 3 的 int 数组的指针”,完全不是同一个东西。
-
var arr [3]*int:声明但未初始化,所有元素为nil -
arr := [3]*int{new(int), new(int), new(int)}:声明并初始化三个非 nil 指针 -
arr := [3]*int{&x, &y, &z}:用已有变量地址初始化
为什么不能用 []*T 替代?
[]*T 是切片,底层是结构体(包含指针、长度、容量),而 [N]*T 是真正的数组,内存连续、大小固定、可直接作为值传递。两者语义和使用场景不同:
- 需要栈上分配、确定大小、避免逃逸时,必须用
[N]*T - 需要动态增删、传参时希望共享底层数组时,才选
[]*T - 函数参数接收
[3]*int和[]*int是不兼容的,不能混用
初始化时容易漏掉的 nil 检查
声明 [3]*int 后直接访问 arr[0] 并解引用会 panic:panic: runtime error: invalid memory address or nil pointer dereference。因为默认初始化为 nil 指针。
立即学习“go语言免费学习笔记(深入)”;
- 必须显式赋值,如
arr[0] = new(int)或arr[0] = &x - 用字面量初始化时,未写的项仍为
nil,例如[3]*int{&x}→[&x, nil, nil] - 如果逻辑依赖非 nil 指针,建议在使用前加
if arr[i] == nil判断
和 C 的关键区别:Go 没有指针算术,数组名不自动转指针
在 C 中,int *arr[3] 声明的是“含 3 个 int* 的数组”,但你可以对 arr 做加减;Go 中 [3]*int 是值类型,arr 本身不是指针,取地址要写 &arr,得到的是 *[3]*int 类型。
-
arr是数组值,可直接赋值、比较(元素可比时) -
&arr才是指向该数组的指针,类型为*[3]*int - 没有
arr + 1这种运算,也不支持下标越界访问(编译期或运行期报错)
数组长度写死、元素为指针——这种组合在需要固定槽位管理对象引用(比如状态机的 handler 表、固定尺寸的缓存槽)时有用,但多数场景下切片更灵活。别为了“像 C”而硬用数组,除非你明确需要它的值语义和栈布局。


















