Golang 1.18 及 1.18.1 中 iota 不从 0 开始

07/Mar/2023 · 1 minute read

一句话读完版

golang 源码中使用了 iota 定义枚举量,并且没有显式声明起始值的话,请确保没有使用 golang 1.18 或者 golang 1.18.1。

详细说明版

背景

昨天在线上系统中发现了一个奇怪的现象,代码中有一行 response.Code == konst.SuccessCode 代码的判断结果总是 false,经过日志核查,确认 response.Code 一定是 0,但是神奇的是 konst.SuccessCode 却是 1,其定义是:

package konst

const SuccessCode = iota

最奇怪的是,goland IDE 提示这个常量解析后的值也是 0。

为什么会是 1 呢?

问题定位

经过使用不同的 golang 版本编译后,在本地复现了这个缺陷,问题出在 golang 1.18 上。具体可看:

https://go-review.googlesource.com/c/go/+/401134/4

此缺陷是由于在 golang 1.18 和 1.18.1 中进行 iota 枚举时,枚举值并不总是从 0 开始递增。在这个问题的修复版本 1.18.2 中,已经修复了这个问题。因此,升级到 1.18.2 版本是解决此问题的最简单方法。另一个解决方法是在定义枚举时指定值 = 0,这将避免出现 iota 值错误的问题。

官方修复的记录见:https://github.com/golang/go/issues/52441

解决方案

解决方案比较简单,可以升级到 golang 1.18.2 版本,这个版本已经修复了这个问题。如果不想升级,也可以在 konst.SuccessCode 的后面加上 = 0,这样就能避免出现 iota 值错误的问题了。

另外,最好的实践是,始终在第一个 iota 上加上 = 0,也能防止以后类似问题的出现。