权限枚举必须用1,即每个枚举值应为2的n次方(如1、2、4、8…),配合[Flags]特性实现位运算,支持权限叠加(|)、判断(&)和移除(^),确保各权限位互不干扰。

权限枚举必须用 1 ,不是 <code>iota
直接写 Read = iota、Write、Exec 会得到 0、1、2 —— 这根本不是位掩码,做按位或时 Read | Write == Exec,逻辑全崩。权限判断依赖独立 bit,必须保证每个值只占一个位。
Read = 1 得到 1(二进制 <code>0001),Write自动是1 = 2(<code>0010),以此类推- 类型建议用
uint:避免负数、符号位干扰,尤其在右移或跨平台编译时更稳定 - 判断权限永远用
perm & Read != 0,别用perm == Read—— 后者只能匹配纯 Read,漏掉Read | Write这类组合
同一 const 块里空行/注释不重置 iota,但下划线 _ 会触发递增
iota 不是“每行加 1”,而是“每次被表达式右侧实际使用才加 1”。空行、注释不影响计数;但写 _ = iota 或 _ 单独成行,就等于用了一次 iota,后续值立刻 +1。
- 常见错误:在 const 块开头加
// 注释或空行,以为能“跳过 0”,结果StatusPending还是 0 —— 因为没用iota,它根本没动 - 正确跳过 0:写
_ = iota(显式消耗一次),再跟StatusPending,这样它才是 1 - 混用字符串或数字字面量(如
ErrUnknown = 1000)会导致后续iota从 0 重新计数,值错位
String() 方法只影响 fmt 输出,不影响 JSON 序列化
给枚举类型实现 String() 后,fmt.Printf("%v", s) 会显示 "pending",但 json.Marshal(s) 仍输出数字 0。这不是 bug,是 Go 的设计选择 —— encoding/json 不调用 String()。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 想 JSON 输出字符串,必须让类型实现
json.Marshaler接口,手动控制序列化逻辑 -
String()方法的default分支不能省:未定义值(比如网络传入非法整数)会走 default,返回 fallback 字符串,避免 panic 或空字符串 - switch 必须覆盖所有已知常量值,否则编译不报错,但运行时可能静默返回空
多个 const 块之间 iota 完全隔离
每个 const 块里的 iota 独立计数,互不影响。误拆枚举到多个块,会导致重复值、语义断裂,且很难 debug。
立即学习“go语言免费学习笔记(深入)”;
- 例如把
StatusPending放第一个 const,StatusRunning放第二个 const,两者都是 0 —— 类型相同、值相同,但语义完全不同 - 位掩码和状态码这类强关联常量,必须放在同一个 const 块里,靠
iota保持相对顺序和数值关系 - 如果真要分组,用注释或空行隔开,别用新 const 块 ——
iota的生命周期只绑定 const 块边界
ErrUnknown = 1000)时会静默重置后续计数,而编译器完全不报错。这种错往往拖到运行时才暴露,且难以定位。

















