2014/12/08

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{51117}

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
Posted at 09:39 | WriteBacks () | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.






















A quick preview will be rendered here when you click "Preview" button.