LoginSignup
1
2

More than 3 years have passed since last update.

Goで設計に役立つEnumの実装を考える

Last updated at Posted at 2019-07-27

はじめに

JavaでEnumを使った設計パターンはよくあるんですが、Goで同等のことをどうやるか考えてみました。

料金区分を例に

現場で役立つシステム設計の原則ではJavaのEnumを使った料金区分の設計と実装が紹介されています。
この例を参考にGoで適用するとどうなるか考えてみました。

まずは本と同様に料金区分をinterfaceで実装します。

type Fee interface {
    Yen() int
    Label() string
}

type adultFee struct{}

func (adultFee) Yen() int {
    return 1500
}

func (adultFee) Label() string {
    return "大人"
}

type childFee struct{}

func (childFee) Yen() int {
    return 1000
}

func (childFee) Label() string {
    return "子供"
}

料金区分(Fee)をinterface
大人料金(adultFee)と子供料金(childFee)はFeeのinterfaceを満たしています。

設計でJavaのEnumを使う魅力

  • 定義したものだけを呼べて、定義していないものを呼び出すとコンパイルエラーになる。
  • valueOfメソッドで文字列からenumの値を取得できる

GoでのEnum実装 - 変数で定義

Goで実装してみます。

var FeeType = struct {
    Adult   Fee
    Child   Fee
    ValueOf func(s string) (fee Fee, err error)
}{
    Adult: adultFee{},
    Child: childFee{},
    ValueOf: func(s string) (fee Fee, err error) {
        switch s {
        case "adult":
            fee = adultFee{}
        case "child":
            fee = childFee{}
        default:
            err = fmt.Errorf("未定義の料金タイプ %s", s)
        }
        return
    },
}

ポイントは定義したものだけを呼び出せるようにstructのメンバーとして定義済みの値を用意しました。
また、valueOfについてもstructのメンバーとして追加しています。

GoでのEnum実装 - 関数で定義

変数での定義が気になる方は、こんな方法も

func FeeType() struct {
    Adult   Fee
    Child   Fee
    ValueOf func(s string) (fee Fee, err error)
} {
    return struct {
        Adult   Fee
        Child   Fee
        ValueOf func(s string) (fee Fee, err error)
    }{
        Adult: adultFee{},
        Child: childFee{},
        ValueOf: func(s string) (fee Fee, err error) {
            switch s {
            case "adult":
                fee = adultFee{}
            case "child":
                fee = childFee{}
            default:
                err = fmt.Errorf("未定義の料金タイプ %s", s)
            }
            return
        },
    }
}

変数と違い関数なので間違っても上書きされないので安心です。

まとめ

今回はGoでJavaのEnum相当の機能を作り込む方法を考えてみました。
こんなやり方もあるよという方がいればコメント欄などで教えてもらえると嬉しいです。

参考

GoでEnumを定義する 〜intやstringよりも厳密に〜

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2