覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Go言語 - enumを定義する

Go言語には、C言語やJavaにおける「enum(列挙型)」のような機能がありません。
Go言語をやり始めて最初にこれを知った時、 え嘘でしょ? と言いたくなりました。

が、実際には 定数定義とiotaを利用することでC言語における列挙型に近い振る舞いを実現することが可能です。
例えば、Red, Blue, Yellowを持つColorというenumを作る場合は以下のように定義します。

type Color int

const (
    Red Color = iota
    Blue
    Yellow
)


で、iotaって何ですかって話なんですが。
識別子iotaは、定数宣言文(const)内で使用される、型なしの連続する整数定数を表します。
本定数は予約語constが現れた時に0に初期化されて、各定数定義の後に1ずつインクリメントされます。
ちなみに読み方は「イオタ」。

例えば、iotaを使って定数(val0, val1, val2)を定義すると、各定数の値は0, 1, 2になります。

const (
    val0 = iota // val0 == 0
    val1 = iota // val1 == 1
    val2 = iota // val2 == 2
)

iotaは 0 から開始され、(以下例のように)iotaを省略しても評価されて連続する整数がセットされます

const (
    val0 = iota // val0 == 0
    val1        // val1 == 1
    val2        // val2 == 2
)


ということで、冒頭のColorは、実際には以下コード内のコメントのように、Redに0, Blueに1, Yellowに2がセットされています。
これにより疑似的にenumを表現しています。

type Color int

const (
    Red Color = iota // Red    == 0
    Blue             // Blue   == 1
    Yellow           // Yellow == 2
)


実際にはenumとして作成したtypeに対してfmt.Stringerインターフェースを実装(Stringメソッドを用意)しておくのが良いです。
Stringerインターフェースを実装しておいた方がfmt.Println等で表示した際に分かりやすくなります)

そこまでやるとColorの定義は以下のようになります。

type Color int

const (
    Red Color = iota
    Blue
    Yellow
)

func (c Color) String() string {
    switch c {
    case Red:
        return "Red"
    case Blue:
        return "Blue"
    case Yellow:
        return "Yellow"
    default:
        return "Unknown"
    }
}

Stringメソッドのこの実装はどうにかならないんだろうかと良く思いますが・・・)


というわけでGo言語でもenumを定義することができました。