Golang 如何表示枚舉類型

枚舉,是一種重要的數據類型,由一組鍵值對組成,通常用來在編程語言中充當常量的標識符。在主流行編程語言如 c、 java 等,都有原生支持。在 go 中,大家卻找不到 enum 或者其它直接用來聲明枚舉類型的關鍵字。從熟悉其它編程語言的開發者轉用 go 編程,剛開始會比較難接受這種情況。其實,如果你看到如何在 go 中表示枚舉類型時,可能會感受到 go 語言設計者對簡潔性、問題考慮的深度,是一般資淺工程師無法比擬的。

其實,在 go 語言設計者的眼裏,enum 本質是常量,爲什麼要多餘一個關鍵字呢?在 go 只是沒有 enum 關鍵字而已,其表現枚舉的形式,與其它語言別無太大區別。下面來看看如果在 go 中表示枚舉。

學習、使用一門語言,是學習、理解語言本身的設計哲學,同時也會感受到設計者的性格特點。

基礎工作 

爲了下面講解方便,這裏使用 go modules 的方式先建立一個簡單工程。

~/Projects/go/examples
➜  mkdir enum

~/Projects/go/examples
➜  cd enum

~/Projects/go/examples/enum
➜  go mod init enum
go: creating new go.mod: module enum

~/Projects/go/examples/enum
➜  touch enum.go

const + iota

以 啓動、運行中、停止 這三個狀態爲例,使用 const 關鍵來聲明一系列的常量值。在 enum.go 中寫上以下內容:

package main

import "fmt"

const (
    Running int = iota
    Pending
    Stopped
)

func main() {
    fmt.Println("State running: ", Running)
    fmt.Println("State pending: ", Pending)
    fmt.Println("State Stoped: ", Stopped)
}

保存並運行,可以得到以下結果,

~/Projects/go/examples/enum 
➜  go run enum.go
State running:  0
State pending:  1
State Stoped:  2

在說明發生了什麼之前,我們先看來一件東西,iota。相比於 c、java,go 中提供了一個常量計數器,iota,它使用在聲明常量時爲常量連續賦值。

比如這個例子,

const (
    a int = iota // a = 0
    b int = iota // b = 1
    c int = iota // c = 2
)
const d int = iota // d = 0

在一個 const 聲明塊中,iota 的初始值爲 0,每聲明一個變量,自增 1。以上的代碼可以簡化成:

const (
    a int = iota // a = 0
    b // b = 1
    c // c = 2
)
const d int = iota // d = 0

設想一下,如果此時有 50 或者 100 個常量數,在 c 和 java 語言中寫出來會是什麼情況。

關於 iota,有更多的具體的技巧(例如跳數),詳細請看官方定義 iota


通過使用 const 來定義一連串的常量,並藉助 iota 常量計數器,來快速的爲數值類型的常量連續賦值,非常方便。雖然沒有了 enum 關鍵字,在這種情況下發現,是多餘的,枚舉本質上就是常量的組合。

當然,你可以使用以下方式,來更接近其它語言的 enum

// enum.go
...
type State int

const (
    Running State = iota
    Pending
    Stopped
)
...

把一組常量值,使用一個類型別名包裹起來,是不是更像其它語言中的 enum {} 定義了呢?

你還可以將上面的例子改爲:

// enum.go
...
type State int

const (
    Running State = iota
    Pending
    Stopped
)
func (s State) String() string {
    switch s {
    case Running:
        return "Running"
    case Pending:
        return "Pending"
    case Stopped:
        return "Stopped"
    default:
        return "Unknown"
    }
}
...

爲定義的枚舉類型加上 String 函數,運行結果如下:

~/Projects/go/examples/enum 
➜  go run enum.go
State running:  Running
State pending:  Pending
State Stoped:  Stopped

是不是很魔幻,思路一下又開闊一些,長見識了。把實際的值與打印字符分開,一般語言設計者不會想到。看到這裏,有沒有這種的感覺,go 語言的設計者並不是偷懶,而是爲了可以偷懶想了很多、做了很多。

轉自:

youwu.today/skill/backend/using-enum-in-golang/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KFVYcF2ykDecnfkcJ7aV8g