【Go言語】RubyやPHPのようにEnumを表現をする方法。iotaの連番の使い方も解説

Go言語にはRubyやPHPとは異なりenum型はありません。

しかし定数のセットを使用して値の「列挙」を表現できます。

Enumっぽく使えるGoのサンプルコードを書いてみます。

Go言語でEnumを表現するサンプルコード

package main

import "fmt"

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

func main() {
    day := Monday

    switch day {
    case Sunday:
        fmt.Println("Sunday")
    case Monday:
        fmt.Println("Monday")
    case Tuesday:
        fmt.Println("Tuesday")
    case Wednesday:
        fmt.Println("Wednesday")
    case Thursday:
        fmt.Println("Thursday")
    case Friday:
        fmt.Println("Friday")
    case Saturday:
        fmt.Println("Saturday")
    }
}

この例では曜日を表す定数のセットを定義しています。これらの定数を使用して特定の曜日を表すことができます。次に、day変数の値に基づいて異なるアクションを実行するためにswitch文を使用します。

Goの定数は強い型付けされており、コンパイル時にのみ値を割り当てることができます。

これは、定数にランタイム計算に基づいて値を割り当てることができないことを意味します。より柔軟性のある値を使用する必要がある場合は、一連の値を持つカスタムタイプを定義することができます。

package main

import "fmt"

type DayOfWeek int

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

func main() {
    day := Monday

    switch day {
    case Sunday:
        fmt.Println("Sunday")
    case Monday:
        fmt.Println("Monday")
    case Tuesday:
        fmt.Println("Tuesday")
    case Wednesday:
        fmt.Println("Wednesday")
    case Thursday:
        fmt.Println("Thursday")
    case Friday:
        fmt.Println("Friday")
    case Saturday:
        fmt.Println("Saturday")
    }
}

この例では、整数としてのカスタムタイプDayOfWeekを定義しています。次にそれらの値を表す定数のセットを定義します。

これらの定数を使用して特定の曜日を表すことができます。 iotaキーワードを使用して、各定数の値を0から開始して自動的に生成します。

※iotaを見慣れてない人もいると思うので、詳細を後述で補足します。

カスタムタイプを定義することで、多くの値をグループ化する必要がある場合、より安全で保守性の高いコードを書くことができます。 ただし、追加の型定義を導入することで、より複雑なコードになる可能性があることに注意してください。

 

iotaとは?

iotaは、Goの組み込み識別子で、連続した整数定数の連番を生成するために使用されます。

iotaは、定数定義内で使用されます。定数定義の最初の要素で使用されると、iota0から開始し、次の要素に進むたびに1ずつインクリメントされます。例えば、以下のように使用することができます。


package main

import "fmt"

func main() {
    const (
        a = iota  // a = 0
        b = iota  // b = 1
        c = iota  // c = 2
    )

    fmt.Println(a, b, c) // 0 1 2
}

上記の例では、iotaは最初の要素で使用され、a0が割り当てられます。次の要素の定義でiotaを使用すると、iota1にインクリメントされ、b1が割り当てられます。同様に、c2が割り当てられます。

定数定義内でiotaを使用するとiotaは自動的にリセットされます。

つまり定数定義の別のセットで再度使用することができます。例えば、以下のように使用することができます。

 


package main

import "fmt"

func main() {
    const (
        a = iota  // a = 0
        b         // b = 1 (iotaが暗黙的に使用される)
        c         // c = 2 (iotaが暗黙的に使用される)
    )

    const (
        d = iota  // d = 0 (iotaがリセットされる)
        e         // e = 1 (iotaが暗黙的に使用される)
        f         // f = 2 (iotaが暗黙的に使用される)
    )

    fmt.Println(a, b, c, d, e, f) // 0 1 2 0 1 2
}

上記の例では、定数定義内で最初にiotaを使用すると、iota0に設定され、a0が割り当てられます。

bcは、iotaが暗黙的に使用されたため1および2が割り当てられます。定数定義の後半で再びiotaを使用するとiotaはリセットされ、d0が割り当てられます。

efは、iotaが暗黙的に使用されたため、1および2が割り当てられます。

 

まとめ

定数定義を使えばEnumのようにも表現できます。