1091 字
约 3 分钟
5
S09-B03 · 常量、iota 与指针
适用读者:用过 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. 自检
iota在同一个const块里跨空行会怎样?q := p; q.X = 2会影响p吗?为什么?- 为什么 Go 不提供指针算术?代价是什么?
var m map[string]int后直接赋值会怎样?- 什么时候该用指针接收者?
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/ 评论
0 条
还没有评论,先写一条吧。