概要
Go には、C#などのように enum という型がありませんが、定数を使って同じような感じにすることが出来ます。
enum と iota に関して、とても参考になった記事があったので、忘れない内にメモメモ。
★ Ultimate Visual Guide to Go Enums and iota | by Inanc Gumus | Learn Go Programming
ついでに自分でもサンプル作ったので、以下にメモメモ。
Enum のサンプル
package enum import ( "github.com/devlights/gomy/output" ) type ( // Status -- サンプル用 enum. 何かのステータスを表す Status int ) // impl -- fmt.Stringer func (s Status) String() string { values := [...]string{ "不明", "実行中", "停止中", } if s < Unknown || Stopped < s { return "不明" } return values[s] } // CanForward -- 先に進めることができるかどうかを返す // // 可能な場合は true, それ以外は false func (s Status) CanForward() bool { switch s { case Running: return true } return false } // ステータス値 const ( Unknown Status = 0 // 不明 Running Status = 1 // 実行中 Stopped Status = 2 // 停止中 ) // GoEnums -- Go における enum の扱い方についてのサンプルです // // REFERNCES: // -https://blog.learngoprogramming.com/golang-const-type-enums-iota-bc4befd096d3 func GoEnums() error { // --------------------------------------------------------------------------- // enum とは関連する値を一つの型でグルーピングするもの // // 例: シャツのサイズ (S, M, L), ステータス (Running, Stopped, Resumed), 曜日 // --------------------------------------------------------------------------- v := Running output.Stdoutl("[Status]", int(v)) // --------------------------------------------------------------------------- // 型を定義するので、振る舞いを追加することができる // // 有名なのが golang.org/x/tools/cmd/stringer で、指定した enum の名称を出力する // String() を自動生成してくれるもの // // $ go get -u -v golang.org/x/tools/cmd/stringer // $ stringer -type Status // // 上記で status_string.go が出力される // --------------------------------------------------------------------------- output.Stdoutl("[Status]", v) output.Stdoutl("[v.CanForward]", v.CanForward()) output.Stdoutl("[Running.CanForward]", Running.CanForward()) output.Stdoutl("[Stopped.CanForward]", Stopped.CanForward()) return nil }
try-golang/go_enums.go at master · devlights/try-golang · GitHub
実行すると以下のようになります。
$ make run ENTER EXAMPLE NAME: go_enums [Name] "go_enums" [Status] 1 [Status] 実行中 [v.CanForward] true [Running.CanForward] true [Stopped.CanForward] false [Elapsed] 0s
iota のサンプル
package enum import ( "github.com/devlights/gomy/output" ) // GoIota -- Go における iota の扱い方についてのサンプルです // // REFERENCES: // -https://blog.learngoprogramming.com/golang-const-type-enums-iota-bc4befd096d3 // //noinspection GoBoolExpressions func GoIota() error { // --------------------------------------------------------------------------- // iota は Goで利用できる数値のカウンタ. // 以下の基本的な特徴を持つ. // // - 0から始まる // - 呼び出すたびに1ずつ加算していく // - const定義の中でのみ利用できる // - リセットできる // // --------------------------------------------------------------------------- type ( Weekday int ) // 基本的な使い方 const ( _ Weekday = iota // 初期値は 0. 曜日は 1 からスタートしたいので捨てる Sunday // = iota を省略可能。値は1となる. _ // iota の値は加算されるが捨てる。つまり2を捨てる // コメントの場合 iota は加算をスキップ。なので増えない。空行の場合も増えない Monday // 3 Tuesday // 4 ) output.Stdoutl("Weekday", Sunday, Monday, Tuesday) // iota は const ブロック 毎にリセットされる const ( Sunday2 Weekday = iota // 0 Monday2 = iota // 1 ) output.Stdoutl("Weekday2", Sunday2, Monday2) // iota を 途中で使うと、そこまで毎行 iota を使っていた状態の値を返す // つまり、以下の場合だと Three の部分で iota を書くと 2 となる // (One の部分で 0 -> 1, Two の部分で 1 -> 2 だから) const ( One = 1 // iota 0 -> 1 Two = 2 // iota 1 -> 2 Three = iota + 1 // iota 2 -> 3 Four = iota + 1 // iota 3 -> 4 ) output.Stdoutl("iota in the middle", One, Two, Three, Four) // iota を同じ行に複数書いても同じ値となる const ( A, B, C = iota, iota, iota // 0, 0, 0 D, E, F // 1, 1, 1 ) output.Stdoutl("iota multiple", A, B, C, D, E, F) // iota を同じ行に複数書くと同じ iota の値を受け取れる const ( V1, V2 = iota, iota + 10 // 0, 10 V3, V4 // 1, 11 // この場合、以下のように一行で一つだけの宣言は *そのまま* できない. コンパイルエラーとなる // 上で一行に2つの iota のパターンを利用しているため // V5, // iota をリセットするのであればオッケイ V5 = iota ) output.Stdoutl("iota multiple2", V1, V2, V3, V4, V5) // Go の const では 直近の表現がキープされる // なので、以下のように 直値 で 1 と指定して次の行に値を指定しない場合 // 直近の表現、つまり 1 がそのままキープされる。 // // なので、iota を指定している場合は、暗黙で次の行でも iota が指定されていることになる const ( First = 1 Second // Second = 1 と同じ ) output.Stdoutl("last used expression keep", First, Second) // iota で フラグ向けの値はよく利用されるパターン // ビット操作で利用することが多い type ( Flg int ) const ( Flg1 Flg = 1 << iota // 1 << 0 --> 0b00000001 --> 1 Flg2 // 1 << 1 --> 0b00000010 --> 2 Flg3 // 1 << 2 --> 0b00000100 --> 4 AllFlgs = Flg1 | Flg2 | Flg3 ) flg := Flg2 | Flg3 output.Stdoutl("iota bitwise value is", flg) if flg&Flg1 == Flg1 { output.Stdoutl("flg & Flg1", "Flg1") } if flg&Flg2 == Flg2 { output.Stdoutl("flg & Flg2", "Flg2") } if flg&Flg3 == Flg3 { output.Stdoutl("flg & Flg3", "Flg3") } if flg&AllFlgs != 0 { output.Stdoutl("flg & AllFlgs", "flg is valid") } wrongFlg := Flg(8) // 8 --> 1 << 3 --> 0b00001000 if wrongFlg&AllFlgs == 0 { output.Stdoutl("Flg(8) & AllFlgs", "Flg(8) is invalid") } return nil }
try-golang/go_iota.go at master · devlights/try-golang · GitHub
実行すると以下のようになります。
$ make run ENTER EXAMPLE NAME: go_iota [Name] "go_iota" Weekday 1 3 4 Weekday2 0 1 iota in the middle 1 2 3 4 iota multiple 0 0 0 1 1 1 iota multiple2 0 10 1 11 2 last used expression keep 1 1 iota bitwise value is 6 flg & Flg2 Flg2 flg & Flg3 Flg3 flg & AllFlgs flg is valid Flg(8) & AllFlgs Flg(8) is invalid [Elapsed] 998.2µs
参考

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者:Alan A.A. Donovan,Brian W. Kernighan
- 発売日: 2016/06/20
- メディア: 単行本(ソフトカバー)
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場