Go语言禁止指针算术是出于安全设计,仅允许取址、解引用和与nil比较;切片封装了安全偏移操作,绝大多数场景应使用切片而非裸指针。

Go 语言原生禁止指针算术(如 ptr + 1、ptr++),这不是遗漏,而是明确的设计取舍——安全优先于底层控制。
为什么编译器直接报错 invalid operation: ptr + 1
Go 把指针定位为“安全间接访问工具”,而非“内存游标”。它只允许三种操作:&(取地址)、*(解引用)、==/!=(与 nil 比较)。所有加减乘除、类型强制转换(如 int 转 *int)都被编译器拦截。
- 根本原因:防止越界读写、悬垂指针、未对齐访问等 C 类内存错误
- 配套机制:切片(
[]T)已封装了安全的索引、截取、扩容逻辑,覆盖了 95% 的“需要偏移”的场景 - 设计哲学:用显式、带边界的抽象(如
slice[i])替代隐式、易错的算术(如*(ptr + i))
真要遍历数组或操作内存怎么办
绝大多数情况,你应该用切片代替裸指针;只有极少数系统级场景(如序列化二进制协议、实现 ring buffer、对接 C 库)才需绕过限制,此时必须显式启用 unsafe 包。
- ✅ 推荐做法:
arr := [4]int{1,2,3,4}; s := arr[:]; for i := range s { fmt.Println(s[i]) } - ⚠️ 非安全但可行(仅限必要时):
p := &arr[0]; base := unsafe.Pointer(p); for i := 0; i - 注意:
unsafe.Pointer不受 GC 保护,不检查边界,不保证跨平台对齐,且一旦用上,整个函数自动逃逸到堆 —— 别为省几行代码引入维护黑洞
常见误踩坑:以为 &arr[0] 是“数组指针”就能算术
&arr[0] 得到的是 *int,不是指向整个数组的指针;它不携带长度信息,也不支持 p[1] 这类语法(那会编译失败)。很多人卡在这里,其实是混淆了两种指针语义:
立即学习“go语言免费学习笔记(深入)”;
-
&arr→ 类型是*[4]int,可安全写(*p)[2]或简写p[2](Go 允许对数组指针直接索引) -
&arr[0]→ 类型是*int,只能访问第一个元素;想访问后续?要么改用切片,要么进unsafe(不推荐) - 错误示例:
ptr := &arr[0]; ptr = ptr + 1→ 编译报错:invalid operation: ptr + 1 (mismatched types *int and int)
最常被忽略的一点:Go 的“不支持指针算术”不是技术做不到,而是刻意把危险操作推到明处——你得敲出 unsafe 这三个字,还得在代码 review 时被所有人盯着。这比静默允许然后等线上 core dump 强得多。









