iota在const块中每次被实际使用时才递增,而非按行递增;空行、注释、_=iota均消耗一次计数,同一行多次使用iota值相同,混用字面量会重置iota,位掩码需显式1

iota 不是“枚举语法糖”,它只在 const 块内有效,且每次被实际用于表达式右侧时才递增 —— 这一点错了,后面全错。
为什么 iota 值对不上:行号 ≠ 递增次数
很多人写完 const 块发现 Write 是 1 而不是想要的 2,根本原因是误以为“每行加 1”。实际上:iota 是“每次被引用时才 +1”,空行、注释、下划线 _ 都不触发递增。
- 同一行写
Read, Write = iota, iota→ 两者都是 0(只用了一次iota) - 写
_ = iota单独一行 → 消耗一次递增,下一行从 1 开始 - 写
Port = 8000 + iota→ 当前行值为 8000,下一行自动变成 8001 - 混用字面量会重置计数:如果某行写
Debug = 100(没用iota),下一行iota仍为 0,不是延续
位掩码必须显式左移:Read = 1 ,不是 <code>Read = iota
直接用 Read = iota 得到的是 0、1、2、3 —— 这不是位掩码,是普通序列。做 Read | Write 会得到 1,和 Execute 冲突,权限判断必然失效。
- 正确写法:
Read = 1 → <code>Read=1、Write=2、Execute=4 - 类型建议用
uint:避免符号位干扰,尤其跨平台或右移时 - 组合权限用
|:ReadWrite = Read | Write - 判断权限必须加括号:
(perm & Read) != 0,否则perm & Read == Read因优先级问题等价于perm & true
带 String() 方法的枚举类型怎么写才不漏 case
光有 iota 常量,日志里还是打印数字。要让 fmt.Println(StatusRunning) 输出 "running",必须定义类型并实现 String()。
- 先声明类型:
type Status int,再让常量属于该类型:StatusRunning Status = iota -
String()方法里 switch 必须覆盖所有已知值,并带default分支返回 fallback(如"status(" + strconv.Itoa(int(s)) + ")") - 不加
default会导致未定义值返回空字符串,调试时极难定位 -
String()不影响 JSON 输出 ——json.Marshal仍输出数字,需额外实现MarshalJSON()
多个 const 块之间 iota 完全独立,别指望复用序列
有些人在一个文件里分多个 const 块组织权限、状态、错误码,以为 iota 会延续,结果全乱了。
- 每个
const块开头,iota都从 0 重新开始 - 不能靠跨块保持顺序;想复用逻辑,应封装成函数或结构体,而非依赖
iota计数 - 若真需要“全局唯一编号”,用
var+init模拟伪常量(但不再是编译期确定) - 不同包、不同文件中的
const块完全隔离,iota无任何关联
最易被忽略的点:位掩码类型没加括号的判断表达式、String() 缺 default、以及把 iota 当运行时变量用 —— 这三处线上 bug 最密集。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











