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
)