天天看點

《Go語言精進之路》讀書筆記 | 使用iota實作枚舉常量

作者:熱愛程式設計的通信人

書籍來源:《Go語言精進之路:從新手到高手的程式設計思想、方法和技巧》

一邊學習一邊整理讀書筆記,并與大家分享,侵權即删,謝謝支援!

附上彙總貼:《Go語言精進之路》讀書筆記 | 彙總_COCOgsta的部落格-CSDN部落格

與其他C家族主流語言(如C++、Java)不同,Go語言沒有提供定義枚舉常量的文法。通常使用常量文法定義枚舉常量:

const (
    Sunday    = 0
    Monday    = 1
    Tuesday   = 2
    Wednesday = 3
    Thursday  = 4
    Friday    = 5
    Saturday  = 6
)
複制代碼           

Go的const文法提供了“隐式重複前一個非空表達式”的機制:

const (
    Apple, Banana = 11, 22
    Strawberry, Grape
    Pear, Watermelon
)
複制代碼           

常量定義的後兩行沒有顯式給予初始指派,Go編譯器将為其隐式使用第一行的表達式,上述定義等價于:

const (
    Apple, Banana = 11, 22
    Strawberry, Grape  = 11, 22
    Pear, Watermelon  = 11, 22
)
複制代碼           

Go在這個機制的基礎上又提供了神器iota,可以定義滿足各種場景的枚舉常量了。

iota是Go語言的一個預定義辨別符,它表示的是const聲明塊(包括單行聲明)中每個常量所處位置在塊中的偏移值(從零開始)。

下面是Go标準庫中sync/mutex.go中的一段枚舉常量的定義:

// $GOROOT/src/sync/mutex.go (go 1.12.7)
const (
    mutexLocked = 1 << iota
    mutexWoken
    mutexStarving
    mutexWaiterShift = iota
    starvationThresholdNs = 1e6
)
複制代碼           

這是一個很典型的诠釋iota含義的例子,我們逐行來看。

mutexLocked = 1 << iota:此時iota的值為0,我們得到mutexLocked這個常量的值為1 << 0,即1。

mutexWoken:根據“隐式重複前一個非空表達式”機制,該行等價于mutexWoken = 1 << iota。由于該行是const塊中的第二行,是以偏移量iota的值為1,我們得到mutexWoken這個常量的值為1<< 1,即2。

mutexStarving:該行等價于mutexStarving = 1 << iota,由于在該行的iota的值為2,是以我們得到mutexStarving這個常量的值為 1 << 2,即4。

mutexWaiterShift = iota:由于該行為第四行,iota的偏移值為3,是以mutexWaiterShift的值就為3。

位于同一行的iota即便出現多次,其值也是一樣的:

const (
    Apple, Banana = iota, iota + 10 // 0, 10 (iota = 0)
    Strawberry, Grape               // 1, 11 (iota = 1)
    Pear, Watermelon                // 2, 12 (iota = 2)
)
複制代碼           

如果要略過iota = 0,從1開始正式定義枚舉常量:

// $GOROOT/src/syscall/net_js.go,go 1.12.7

const (
    _ = iota
    IPV6_V6ONLY                     // 1
    SOMAXCONN                       // 2
    SO_ERROR                        // 3
)
複制代碼           

也可以使用類似方式略過某一枚舉值:

const (
    _ = iota                        // 0
    Pin1
    Pin2
    Pin3
    _                               // 相當于_ = iota,略過了4這個枚舉值
    Pin5                            // 5
)
複制代碼           

iota的加入讓Go在枚舉常量定義上的表達力大增,主要展現在如下幾方面。

(1)iota可以參與常量初始化表達式的計算,為枚舉常量賦初值

(2)Go的枚舉常量不限于整型值,也可以定義浮點型的枚舉常量

(3)iota使得維護枚舉常量清單更容易

(4)使用有類型枚舉常量保證類型安全