Skip to content

04 特殊的枚举声明

  • iota 是 一个常量生成器,用于创建一系列递增的常量值。
  • 它通常用于声明枚举常量、位掩码(bitmask)等场景,能够简化代码书写并提高可读性。
  • 每次 const 块开始时,iota 的值都会从 0 开始递增,然后在每行常量声明时递增 1。

基本使用

iota 的值在 const 语句块中每增加一行,都会自动递增 1。

go
package main

import "fmt"

const (
    Apple = iota  // Apple 的值是 0
    Banana        // Banana 的值是 1
    Cherry        // Cherry 的值是 2
)

func main() {
    fmt.Println(Apple, Banana, Cherry)  // 输出:0 1 2
}

如何工作

  • iota 的值从 0 开始,在每个新的 const 块中都会重置为 0
  • 每当 iota 出现在一个常量表达式中时,它的值就会递增 1。
  • 可以用于生成一组递增的枚举值,也可以用于更复杂的常量表达式。

跳过值

可以在定义时使用占位符 _ 来跳过某些 iota 值。

go
const (
    _  = iota   // 跳过 iota = 0
    One         // One 的值是 1
    Two         // Two 的值是 2
    Three       // Three 的值是 3
)

fmt.Println(One, Two, Three)  // 输出:1 2 3

结合位操作(位掩码)

iota 常用于位移操作生成一组常量值,这种方式在定义按位掩码(bitmask)时非常有用。

go
const (
    Readable   = 1 << iota  // 1 左移 0 位,值为 1(1 << 0 = 1,表示可读权限)
    Writable                // 1 左移 1 位,值为 2(1 << 1 = 2,表示可写权限)
    Executable              // 1 左移 2 位,值为 4(1 << 2 = 4,表示可执行权限)
)

fmt.Println(Readable, Writable, Executable)  // 输出:1 2 4

复杂表达式中的 iota

iota 可以与自定义表达式结合,生成更复杂的常量值。

go
const (
    KB = 1 << (10 * iota)  // 1 左移 10 位,1024。表示 1 KB
    MB                     // 1 左移 20 位,1048576。表示 1 MB
    GB                     // 1 左移 30 位,1073741824。表示 1 GB
)

fmt.Println(KB, MB, GB)  // 输出:1024 1048576 1073741824

重复使用 iota 的值

在同一行中声明多个常量时,iota 的值不会改变。

go
const (
    a, b = iota, iota + 5  // a = 0, b = 5
    c, d                   // c = 1, d = 6
    e, f                   // e = 2, f = 7
)

fmt.Println(a, b, c, d, e, f)  // 输出:0 5 1 6 2 7

枚举类型中的 iota

iota 常用于定义枚举类型(enumerated type),能够直观地表示一系列相关值。

go
type Weekday int

const (
    Sunday Weekday = iota  // Sunday 的值是 0
    Monday                 // Monday 的值是 1
    Tuesday                // 2
    Wednesday              // 3
    Thursday               // 4
    Friday                 // 5
    Saturday               // 6
)

fmt.Println(Sunday, Monday, Tuesday)  // 输出:0 1 2

iota 重置规则

每个 const 块的 iota 值都会从 0 开始。

go
const (
    A = iota  // A = 0
    B         // B = 1
)

const (
    C = iota  // C = 0(新 const 块,iota 被重置)
    D         // D = 1
)

const (
    FlagNone = iota    // 0
    FlagRed            // 1
    FlagGreen          // 2
    FlagBlue           // 3
)

const (
    LevelLow = iota + 1  // 1
    LevelMedium          // 2
    LevelHigh            // 3
)

fmt.Println(A, B, C, D)  // 输出:0 1 0 1
fmt.Println(FlagNone, FlagRed, FlagGreen, FlagBlue)  // 输出:0 1 2 3
fmt.Println(LevelLow, LevelMedium, LevelHigh)  // 输出:1 2 3

忽略 iota 的值

可以使用占位符 _ 来忽略不需要的 iota 值。

go
const (
    _, x, y = iota, iota + 10, iota + 20  // _, x = 0, 10, y = 0 + 20
    _, a, b = iota, iota + 10, iota + 20  // _, a = 1, 11, b = 1 + 20
)

fmt.Println(x, y, a, b)  // 输出:10 20 11 21