Created
July 14, 2021 18:34
-
-
Save hatappo/1b06eb02168e835ada591c4551143f0b to your computer and use it in GitHub Desktop.
Golang で enum をどう実装するか
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "fmt" | |
| enum "github.com/hatappo/go-skelton/main/enum" | |
| ) | |
| func main() { | |
| hoge := enum.SeasonValueOf("ほげ") | |
| fmt.Printf("'ほげ' は '%s' の季節です。\n", hoge.Ja()) | |
| fmt.Println("--------------------") | |
| w := enum.SeasonValueOf("WINTER") | |
| fmt.Printf("'WINTER' は日本語だと '%s' です。\n", w.Ja()) | |
| fmt.Printf("'WINTER' は英語ならば '%s' です。\n", w.En()) | |
| fmt.Printf("'WINTER' の次の季節は '%s' です。\n", w.Next().En()+"("+w.Next().Ja()+")") | |
| fmt.Println("--------------------") | |
| a := enum.SeasonValueOf("秋") | |
| fmt.Printf("'%s' は '%s' の次の季節でしょうか?: %t 。\n", w.Ja(), a.Ja(), w.IsNextOf(enum.Autumn)) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package enum | |
| import "strings" | |
| type Season int | |
| // enum の本体。実体は iota による int 値なのはよくあるそのまま。 [1] | |
| const ( | |
| Unknown Season = iota | |
| Spring | |
| Summer | |
| Autumn | |
| Winter | |
| ) | |
| func (s Season) Ja() string { return s.get().Ja } // 日本語表記文字列を返す | |
| func (s Season) En() string { return s.get().En } // 英語表記文字列を返す | |
| func (s Season) Next() Season { return s.get().Next } // 次の季節を返す | |
| func (s Season) Prev() Season { return s.get().Prev } // 前の季節を返す | |
| func (s Season) IsNextOf(other Season) bool { return s.Prev() == other } // 次の季節かどうかを判定 | |
| func (s Season) IsPrevOf(other Season) bool { return s.Next() == other } // 前の季節かどうかを判定 | |
| func (s Season) String() string { return s.Ja() } // ログ出力を考慮して String() も実装しておく | |
| // 文字列表現などから enum を生成する関数。ウェブ開発などでビュー層からもらった文字列から作りたいときによく使う。 | |
| func SeasonValueOf(s string) Season { // hash lookup is more suitable than linear search? | |
| for _, season := range seasons { | |
| if strings.EqualFold(s, season.En) || s == season.Ja { | |
| return season.V | |
| } | |
| } | |
| return Unknown | |
| } | |
| // Season enum の多様な属性(情報)を表現する構造体の型 | |
| type attr struct { | |
| V Season | |
| Ja string | |
| En string | |
| Next Season | |
| Prev Season | |
| } | |
| // enum の値に応じた属性(情報)を実際に定義している。 [2] | |
| var seasons = [cnt]attr{ | |
| {Unknown, "未定義", "unknown", Unknown, Unknown}, | |
| {Spring, "春", "Spring", Summer, Winter}, | |
| {Summer, "夏", "Summer", Autumn, Spring}, | |
| {Autumn, "秋", "Autumn", Winter, Summer}, | |
| {Winter, "冬", "Winter", Spring, Autumn}, | |
| } | |
| // enum のバリエーション数。これを定数化し [2] と [3] の両方に使っているのがみそだと思っている。 | |
| // enum が拡張されて [1] や [2] のバリエーション数が増えた場合、この cnt も変更され、 [3] の境界条件判定も自動で更新される。 | |
| const cnt = 5 | |
| // enum 値から属性情報をひっぱってくるメソッド。ここでありえない enum 値を制御できる。 [3] | |
| func (s Season) get() attr { | |
| if s < 0 || s >= cnt { | |
| return seasons[0] // or panic("Illegal enum value.") | |
| } | |
| return seasons[s] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment