GoLangでJavaのenumっぽいライブラリ作った話 - おいぬま日報なんとかなるわけなんだけど、これを毎回書くのは面倒なので...
もっと良いやり方があったらぜひ教えて欲しいところです。
http://oinume.hatenablog.com/entry/introducing-goenum
golang でユーザ型の値を文字列化する場合 Stringer というインタフェースを実装します。具体的には
func (l Lang) String() string {
switch l {
case Go:
return "Go"
case Python:
return "Python"
case Ruby:
return "Ruby"
}
panic("Unknown value")
}
上記サイトで書かれている様に String()
という関数を実装します。実は golang のオフィシャルから stringer という、その名の通りのツールが提供されています。
まず、Stringer を実装していないコードを書きます。
package main
import (
"fmt"
)
type Fruit int
const (
Apple Fruit = iota
Orange
Banana
)
func main() {
var fruit Fruit = Apple
fmt.Println(fruit)
}
このまま実行すると 0
と表示されます。ここで以下の様にして stringer というツールをインストールします。
$ go get golang.org/x/tools/cmd/stringer
そしてソースコードと同じディレクトリで以下の様に実行します。
$ stringer -type Fruit fruit.go
すると fruit_string.go
というファイル名の以下のコードが生成されます。
// generated by stringer -type Fruit fruit.go; DO NOT EDIT
package main
import "fmt"
const _Fruit_name = "AppleOrangeBanana"
var _Fruit_index = [...]uint8{5, 11, 17}
func (i Fruit) String() string {
if i < 0 || i >= Fruit(len(_Fruit_index)) {
return fmt.Sprintf("Fruit(%d)", i)
}
hi := _Fruit_index[i]
lo := uint8(0)
if i > 0 {
lo = _Fruit_index[i-1]
}
return _Fruit_name[lo:hi]
}
あとはこのソースも含めてビルドし、再度実行してみると今度は Apple
と表示される様になります。便利ですね。
尚、const
で iota を使う場合ですが、上記の様に型を指定しておくと違う型の変数へ Apple を代入する際にエラーが出て便利です。
package main
import (
"fmt"
)
type Fruit int
type Animal int
const (
Apple Fruit = iota
Orange
Banana
)
const (
Monkey Animal = iota
Elephant
Pig
)
func main() {
var fruit Fruit = Apple
fmt.Println(fruit)
fruit = Elephant
fmt.Println(fruit)
}
./fruit.go:26: cannot use Elephant (type Animal) as type Fruit in assignment