Go 中 iota 枚举常量的用法
FreeGuideOnline
最新
2026-07-07
go package main
import "fmt"
const ( Sunday = iota // 0 Monday // 1 Tuesday // 2 Wednesday // 3 Thursday // 4 Friday // 5 Saturday // 6 )
func main() { fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) }
在第一个常量 `Sunday = iota` 之后,后续的常量如果没有显式给出表达式,就会**自动重复上一行的表达式**。因此 `Monday` 实际上等价于 `Monday = iota`,以此类推。
### 从指定值开始
你可以在第一行通过表达式改变 `iota` 的起始值,后续常量依然基于前一行模式。
```go
const (
_ = iota // 跳过 0
KB = 1 << (10 * iota) // 1 << 10 -> 1024
MB // 1 << 20 -> 1048576
GB // 1 << 30 -> 1073741824
TB // 1 << 40 -> 1099511627776
)
这里用匿名变量 _ 跳过了 0,让 KB 从 1 开始,同时利用 iota 的递增特性生成了 2^10、2^20、2^30、2^40 等常见存储单位。
同一行多个常量
在一行中声明多个常量时,iota 的值在该行是相同的,每换一行才会递增。
const (
x, y = iota, iota + 3 // 0, 3
a, b // 1, 4
c, d // 2, 5
)
这种写法可以快速生成有特定偏移关系的常量对。
进阶技巧
跳过某个值
有时需要保留某个值或跳过不连续的序列,可以使用下划线 _ 作为占位符。
type Priority int
const (
PriorityLow Priority = iota + 1 // 1
_ // 2 被跳过
PriorityMedium // 3
_ // 4 被跳过
PriorityHigh // 5
)
这里 PriorityMedium 实际值为 3,PriorityHigh 为 5。通过 _ 跳过的位置仍然会消耗 iota 的计数。
自定义类型枚举
将 iota 与自定义类型结合,可以创建类型安全的枚举,并为其添加方法。
type Status int
const (
StatusPending Status = iota // 0
StatusRunning // 1
StatusDone // 2
StatusCanceled // 3
)
func (s Status) String() string {
switch s {
case StatusPending:
return "Pending"
case StatusRunning:
return "Running"
case StatusDone:
return "Done"
case StatusCanceled:
return "Canceled"
default:
return "Unknown"
}
}
这样 Status 类型的变量在格式化输出时会显示易读的字符串。
位掩码(Bitmask)
利用 iota 结合位移运算,可以很方便地定义一组用于位运算的常量,常用于标志位(flags)场景。
type Permission uint8
const (
PermRead Permission = 1 << iota // 1 << 0 = 1
PermWrite // 1 << 1 = 2
PermExecute // 1 << 2 = 4
PermAdmin // 1 << 3 = 8
)
func main() {
var perm Permission = PermRead | PermWrite // 3
fmt.Printf("%04b\n", perm) // 0011
}
后续检查权限只需使用位与运算即可:
if perm&PermWrite != 0 {
fmt.Println("可写")
}
表达式中的复杂逻辑
iota 不仅可以单独使用,还能参与任意表达式,只要该表达式在常量编译时可求值。这为生成规律复杂的常量序列提供了灵活性。
const (
ReadOnly = 1 << (iota + 1) // 1 << 1 = 2
WriteOnly // 1 << 2 = 4
ReadWrite // 1 << 3 = 8
)