1091 字
约 3 分钟
5
S09-B03 · 常量、iota 与指针
2024-12-31
2026-11-07

适用读者:用过 Go 但被 iota 和"指针接收者"绕晕的人。
前置:S09-B02。
实测环境:Go 1.22.2(2026-11-05)。
覆盖旧文:A-1451(18) A-1452(31) A-1453(71) = 120 点。
覆盖扩展:E-S09-004(值语义 vs 指针语义)。
上一篇:S09-B02 · 变量与基本类型:为什么 len("中文") 是 6 不是 2
下一篇:S09-B04 · 数组与切片。


1. 一句话结论

Go 的常量是"无类型的高精度数",iota 是编译器给的递增计数器;指针能改值但不能做算术——这两条都是为了"让程序更难写错"。


2. 常量与 iota

const (
	A = iota      // 0
	B             // 1(隐式沿用上一行表达式)
	C             // 2
)

type Weekday int
const (
	Sunday Weekday = iota   // 0
	Monday                  // 1
	...
)

// 位移组合(权限位)
const (
	Read  = 1 << iota   // 1
	Write               // 2
	Exec                // 4
)

iota 的三条规则:

规则 说明
每个 const 块从 0 开始 跨块重新计数
每遇到一行常量声明 +1 空行也算
隐式重复上一行表达式 所以 B、C 不用写 = iota

注意:中途插入一行会打乱后面的值——这是 iota 最常见的坑。


3. 指针:能改值,不能做算术

实测(值拷贝 vs 指针):

type P struct{ X int }
p := P{1}
q := p           // 值拷贝
q.X = 2
pr := &p
pr.X = 3
// 输出:值拷贝 q.X = 2  指针后 p.X = 3
操作 结果
q := p; q.X = 2 p.X 仍是 1(独立副本)
pr := &p; pr.X = 3 p.X 变 3(同一份数据)

3.1 为什么没有指针算术

C 里 p+1 会移动到下一块内存——这是越界与内存破坏的主要来源。Go 直接不提供该能力:指针只能解引用、取地址、比较(nil)。

代价:需要遍历数组时不能用指针走,只能用索引或 range。
收益:几乎消除了"指针越界"这一类漏洞。

3.2 什么时候用指针(E-S09-004)

场景 用指针
需要在函数内修改入参 ✅
结构体很大(避免拷贝) ✅
需要表达"可能不存在" ✅(nil)
方法接收者需要改字段 ✅(指针接收者)
小结构体、只读 ❌(值更简单、更安全)

判据:"这个值需要被共享修改吗?" 是 → 指针;否 → 值。


4. nil 的边界

类型 nil 能否直接使用
指针 解引用会 panic
map 读可以(返回零值)、写会 panic
slice 读可以、append 可以(自动分配)
channel 收发都会阻塞
interface 与"值为 nil 的具体类型"不同(经典坑)
var m map[string]int
m["a"] = 1        // panic: assignment to entry in nil map
var s []int
s = append(s, 1)  // OK

5. 五个误区

误区 真相
"iota 是枚举值" 它只是"行号计数器",你可以用它算任何东西
"Go 指针和 C 一样" 没有算术、不能强转(unsafe 除外)
"值传递一定安全" 传大结构体会拷贝,性能可能有代价
"nil map 可以写" 写会 panic,读返回零值
"接收者用值还是指针无所谓" 影响方法能否修改状态、以及是否满足接口

6. 自检

  1. iota 在同一个 const 块里跨空行会怎样?
  2. q := p; q.X = 2 会影响 p 吗?为什么?
  3. 为什么 Go 不提供指针算术?代价是什么?
  4. var m map[string]int 后直接赋值会怎样?
  5. 什么时候该用指针接收者?

7. 下一篇

S09-B04 · 数组与切片:切片的本质是三字段

指针讲完,下一篇讲 Go 最容易出 bug 的结构:切片。会实测"改切片影响原数组"与 cap 增长序列。


本篇属于系列《S09 · Go 语言》。旧文来源:A-1451–A-1453;扩展点 E-S09-004。值/指针行为为 Go 1.22.2 实测。

S09-B03 · 常量、iota 与指针
https://www.clxhxhhr.top/posts/5301/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。