必须显式绑定类型并用占位符跳过0:先定义type Status int,再写_ = iota和Active Status = iota;权限枚举须用位移,如Read Perm = 1,避免值重复导致逻辑错误。

const 块里没写类型,iota 生成的只是裸整数
Active = iota 编译能过,但 Active 是 untyped int,不是你想要的 Status 类型。它不能直接传给 func f(s Status),也不能作为结构体字段(如 State Status)。Go 不会自动转换,要么编译报错,要么逼你写 Status(Active)——这种强制转换极易遗漏,尤其在大量函数调用或 JSON 序列化时。
必须显式绑定类型:
- 先定义
type Status int - 再在 const 块中写
Active Status = iota - 后续常量(
Inactive、Pending)自动继承该类型,无需重复声明
iota 从 1 开始?别用 +1,用 _ = iota 跳过 0
0 常被误判为“未初始化”或“无效状态”,所以工程中普遍避开。写 Active = iota + 1 看似简单,但新增枚举项时容易漏改表达式,导致值错位。最安全的做法是用占位符消耗一次计数:
-
_ = iota—— 这行不导出、不参与逻辑,只让 iota 变成 1 - 下一行
Active就是 1,Inactive是 2,以此类推 - 若需从 100 开始(如 HTTP 状态码),写
_ = iota + 99,并加注释说明意图
权限枚举必须用位移,不能直接用 iota = 0, 1, 2
写 Read = iota、Write、Exec 得到的是 0、1、2,不是 1、2、4。结果 Read | Write == 1,和 Write 值完全相同,权限判断逻辑直接崩溃。
立即学习“go语言免费学习笔记(深入)”;
- 类型建议用
type Perm uint,避免有符号整数左移溢出 - 正确写法:
Read Perm = 1 ,然后 <code>Write、Exec自动得 2、4 - 判断权限必须用
if p & Read != 0,而不是p == Read—— 后者无法识别组合权限(如Read | Write)
fmt.Println 打印还是数字?String() 方法不是可选项
fmt.Println(status) 输出数字,是因为没实现 String() string 方法。iota 只生成值,不带语义映射 —— 这不是 bug,是 Go 的设计约束。
- 方法签名必须严格是
func (s Status) String() string,接收者类型不能是*Status或其他变体 - switch 分支要覆盖所有已知常量,并带
defaultfallback(如return "status(" + strconv.Itoa(int(s)) + ")"),否则非法值会静默返回空字符串 - 注意:
String()只影响fmt系列函数,对json.Marshal完全无效 —— 那里还得单独实现MarshalJSON()
iota 的递增时机:它只在“该行右侧真正用了 iota”时才加 1,空行、注释、甚至 _ = 123 都不触发。写错一行,后面全偏。


















