golang 使用 iota


iota是golang語言的常量計數器,只能在常量的表達式中使用。

iota在const關鍵字出現時將被重置為0(const內部的第一行之前),const中每新增一行常量聲明將使iota計數一次(iota可理解為const語句塊中的行索引)。

使用iota能簡化定義,在定義枚舉時很有用。

舉例如下:

1、iota只能在常量的表達式中使用。

fmt.Println(iota)
編譯錯誤: undefined: iota

2、每次 const 出現時,都會讓 iota 初始化為0.【自增長】

const a = iota // a=0
const (
  b = iota          //b=0
  c                      //c=1
)

 

3、自定義類型

自增長常量經常包含一個自定義枚舉類型,允許你依靠編譯器完成自增設置。

type Stereotype int

const (
    TypicalNoob Stereotype = iota // 0
    TypicalHipster                               // 1
    TypicalUnixWizard                         // 2
    TypicalStartupFounder                // 3
)

下面是來自time包的例子,它首先定義了一個Weekday命名類型,然后為一周的每天定義了一個常量,從周日0開始。在其它編程語言中,這種類型一般被稱為枚舉類型。

type Weekday int

const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

周一將對應0,周一為1,如此等等。

4、可跳過的值

設想你在處理消費者的音頻輸出。音頻可能無論什么都沒有任何輸出,或者它可能是單聲道,立體聲,或是環繞立體聲的。
這可能有些潛在的邏輯定義沒有任何輸出為 0,單聲道為 1,立體聲為 2,值是由通道的數量提供。
所以你給 Dolby 5.1 環繞立體聲什么值。
一方面,它有6個通道輸出,但是另一方面,僅僅 5 個通道是全帶寬通道(因此 5.1 稱號 - 其中 .1 表示的是低頻效果通道)。
不管怎樣,我們不想簡單的增加到 3。
我們可以使用下划線跳過不想要的值。

type AudioOutput int

const (
    OutMute AudioOutput = iota // 0
    OutMono                       // 1
    OutStereo                     // 2
    _
    _
    OutSurround                // 5
)

5、位掩碼表達式

iota 可以做更多事情,而不僅僅是 increment。更精確地說,iota 總是用於 increment,但是它可以用於表達式,在常量中的存儲結果值。

type Allergen int

const (
    IgEggs Allergen = 1 << iota // 1 << 0 which is 00000001
    IgChocolate                             // 1 << 1 which is 00000010
    IgNuts                                       // 1 << 2 which is 00000100
    IgStrawberries                        // 1 << 3 which is 00001000
    IgShellfish                                // 1 << 4 which is 00010000
)

這個工作是因為當你在一個 const 組中僅僅有一個標示符在一行的時候,它將使用增長的 iota 取得前面的表達式並且再運用它,。在 Go 語言的 spec 中, 這就是所謂的隱性重復最后一個非空的表達式列表。

如果你對雞蛋,巧克力和海鮮過敏,把這些 bits 翻轉到 “on” 的位置(從左到右映射 bits)。然后你將得到一個 bit 值 00010011,它對應十進制的 19。

fmt.Println(IgEggs | IgChocolate | IgShellfish)

// output:
// 19

我們也可以在復雜的常量表達式中使用iota,下面是來自net包的例子,用於給一個無符號整數的最低5bit的每個bit指定一個名字:

type Flags uint

const (
    FlagUp Flags = 1 << iota // is up
    FlagBroadcast            // supports broadcast access capability
    FlagLoopback             // is a loopback interface
    FlagPointToPoint         // belongs to a point-to-point link
    FlagMulticast            // supports multicast access capability
)

隨着iota的遞增,每個常量對應表達式1 << iota,是連續的2的冪,分別對應一個bit位置。使用這些常量可以用於測試、設置或清除對應的bit位的值:

測試結果:

image

隨着iota的遞增,每個常量對應表達式1 << iota,是連續的2的冪,分別對應一個bit位置。使用這些常量可以用於測試、設置或清除對應的bit位的值:

package main

import (
    "fmt"
)

type Flags uint

const (
    FlagUp           Flags = 1 << iota // is up
    FlagBroadcast                      // supports broadcast access capability
    FlagLoopback                       // is a loopback interface
    FlagPointToPoint                   // belongs to a point-to-point link
    FlagMulticast                      // supports multicast access capability
)

func IsUp(v Flags) bool     { return v&FlagUp == FlagUp }
func TurnDown(v *Flags)     { *v &^= FlagUp }
func SetBroadcast(v *Flags) { *v |= FlagBroadcast }
func IsCast(v Flags) bool   { return v&(FlagBroadcast|FlagMulticast) != 0 }

func main() {
    var v Flags = FlagMulticast | FlagUp
    fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true"
    TurnDown(&v)
    fmt.Printf("%b %t\n", v, IsUp(v)) // "10000 false"
    SetBroadcast(&v)
    fmt.Printf("%b %t\n", v, IsUp(v))   // "10010 false"
    fmt.Printf("%b %t\n", v, IsCast(v)) // "10010 true"
}

運行結果:

10001 true

10000 false

10010 false

10010 true

6、定義數量級

type ByteSize float64

const (
    _           = iota                   // ignore first value by assigning to blank identifier
    KB ByteSize = 1 << (10 * iota)       // 1 << (10*1)
    MB                                   // 1 << (10*2)
    GB                                   // 1 << (10*3)
    TB                                   // 1 << (10*4)
    PB                                   // 1 << (10*5)
    EB                                   // 1 << (10*6)
    ZB                                   // 1 << (10*7)
    YB                                   // 1 << (10*8)
)

下面是一個更復雜的例子,每個常量都是1024的冪:

const (
    _ = 1 << (10 * iota)
    KiB // 1024
    MiB // 1048576
    GiB // 1073741824
    TiB // 1099511627776             (exceeds 1 << 32)
    PiB // 1125899906842624
    EiB // 1152921504606846976
    ZiB // 1180591620717411303424    (exceeds 1 << 64)
    YiB // 1208925819614629174706176
)

不過iota常量生成規則也有其局限性。例如,它並不能用於產生1000的冪(KB、MB等),因為Go語言並沒有計算冪的運算符。

7、定義在一行的情況

const (
    Apple, Banana = iota + 1, iota + 2
    Cherimoya, Durian
    Elderberry, Fig
)

iota 在下一行增長,而不是立即取得它的引用。

// Apple: 1
// Banana: 2
// Cherimoya: 2
// Durian: 3
// Elderberry: 3
// Fig: 4

8、中間插隊

const (
    i = iota
    j = 3.14
    k = iota
    l
)

那么打印出來的結果是 i=0,j=3.14,k=2,l=3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM