以範例學 Go:列舉類型

列舉類型(enums)是 代數資料類型 的特殊情況。一種列舉類型有一個固定數量的可能數值,每個數值都有不同的名稱。Go 沒有列舉類型作為一種不同的語言功能,但使用現有的語言習慣很容易實現列舉類型。

package main
import "fmt"

我們的列舉類型 ServerState 有底層 int 型態。

type ServerState int

ServerState 的可能數值被定義為常數。特別關鍵字 iota 自動產生連續的常數數值;在這個情況中為 0、1、2 等。

const (
    StateIdle = iota
    StateConnected
    StateError
    StateRetrying
)

透過實作 fmt.Stringer 介面,ServerState 的數值可以被列印出來或轉換成字串。

如果有很多可能的數值會變得繁瑣。在這種情況下,stringer 工具 可以搭配 go:generate 自動化處理這個程序。請參閱 這篇文章 以取得更詳細的說明。

var stateName = map[ServerState]string{
    StateIdle:      "idle",
    StateConnected: "connected",
    StateError:     "error",
    StateRetrying:  "retrying",
}
func (ss ServerState) String() string {
    return stateName[ss]
}

如果我們有一個 int 型態的數值,我們無法將它傳遞給 transition - 編譯器會抱怨型態不符。這為列舉類型提供了一定程度的編譯時型態安全性。

func main() {
    ns := transition(StateIdle)
    fmt.Println(ns)
    ns2 := transition(ns)
    fmt.Println(ns2)
}

transition 模擬伺服器的狀態轉換;它取出現有狀態並傳回新狀態。

func transition(s ServerState) ServerState {
    switch s {
    case StateIdle:
        return StateConnected
    case StateConnected, StateRetrying:

假設我們在此處檢查一些謂詞以確定下一個狀態…

        return StateIdle
    case StateError:
        return StateError
    default:
        panic(fmt.Errorf("unwknown state: %s", s))
    }
    return StateConnected
}
$ go run enums.go
connected
idle

下一個範例:結構嵌入