2014/09/26


先日、golang の開発リポジトリに generate が入りました。

Go generate: A Proposal

The go build command automates the construction of Go programs but sometimes preliminary processing is required, processing that go build does not support.

https://docs.google.com/document/d/1V03LUfjSADDooDMhe-_K59EgpTEm3V8uvQRuNMAEnjg/edit

皆さんが期待している様な物なのかそうでないのか分かりませんが、ひとまずこの提案書を見る限り

  • 使うのはライブラリユーザではなくライブラリ作者
  • go build で自動で generate してくれる機能はない
  • shell 的なワンライナーは実行出来ない

どちらかと言うと使用するのは開発時で、バイナリを同梱する目的で golang のソースを吐くまでの手順であったり、構造体に特殊なメソッドを生やしたりという目的で使われます。また yacc のソースから golang のソースを吐くなどといった用途も考えられます。生成される物が golang のソースに限られている訳でもありません。

この特殊なメソッドを吐き出す、と聞くとどうしても generics を思い浮かべる方が多いと思いますが、上記の通り「自動では生成されない」という制限がある事から期待されている使い方は現状出来ません。

今日はこの新しく入った generate を使って、どの様な効果が得られるのかを gen というツールを使って説明したいと思います。

まず以下のコード(food.go)を用意します。

//go:generate gen -force

package food

// +gen *
type Food struct {
    Name string
    Price int
}

gen というツールが +gen となっている部分を扱います。

clipperhouse/gen - GitHub

README.md What’s this? gen is a code-generation tool for Go. It’s intended to offer generics-like fu...

https://github.com/clipperhouse/gen

gen はこの識別が付いている type 宣言から便利な関数群を作ってくれます。

food.go があるフォルダで以下を実行します。

$ go generate

すると food_gen.go というコードが生成されます。少し大きすぎるので gist に貼りつけました。詳しくは gen の README を参照して頂きたいですが、配列を扱う上で便利な関数群が生成されます。

あとはこれを使って処理を書くのみとなります。

package main

import (
    "fmt"
    . "github.com/mattn/go-example/food"
)

func main() {
    foods := Foods{
        {"リンゴ"110},
        {"みかん"70},
        {"メロン"400},
    }

    foods.All(func(f *Food) bool {
        if f.Price < 200 {
            fmt.Println(f.Name)
        }
        return true
    })
}

この例は gen を使いましたが、go-assetsgo-bindata でバイナリからソースファイルを生成したり、msgp を使って構造体を MessagePack 対応したりといった用途にも使用出来るかと思います。

ライブラリユーザではなくライブラリ開発者にとっては便利な機能だと思いますね。

Posted at by



2014/08/22


誰も作ってくれないので自分で作った。

mattn/ujihisa - GitHub
https://github.com/mattn/ujihisa

golang で書かれています。go get github.com/mattn/ujihisa/ujm でインストール出来ます。使い方は

$ ujm [filename]

です。ファイル名が無い場合は標準入力から読み取ります。ベースは whitespace です。スペース文字が 便利、タブ文字が 感極まってきました に置き換わります。whitespace に慣れている人ならスイスイと書けるかと思います。例えば

便利便利便利感極まってきました
感極まってきました
便利感極まってきました



この様なコードなら 1 という数字が出力されます。

なお、便利 という文字を出力するにはこれくらいのコードが必要になります。golang で書かれているので Windows でも動きますし、文字の表示でユニコードを使うと Windows でも問題なく表示されます。

とても便利だと思うので、ぜひ使ってみて下さい。

Posted at by



2014/07/30


golang には logger が星の数ほどあるのですが

go言語におけるロギングについて — さにあらず

コマンドラインオプションについて 分かり辛いので、僕の分かった事だけをメモしておきます。 ログの出力処理は glog.go#output を読めば大体分かります。 -logtostderr これを指定...

http://blog.satotaichi.info/logging-frameworks-for-go

その殆どがエスケープシーケンスを使って色を出しており、Windows で動かすと残念な表示になる物ばかりでした。

まさかログに色を付けたいという理由だけで ansicon を使うのは悲し過ぎるし、そもそも「ansicon 使ったら負けだと思ってる」ので、go-colorable というライブラリを書きました。

golang の logger はその殆どが標準パッケージの log を参考にしており、おおよそ SetOutput という、出力先を変えられる関数が用意されています。そこで、それを横取りして Windows でも色を出せる様にしました。

mattn/go-colorable - GitHub
https://github.com/mattn/go-colorable

これを使うと今まで

bad

こんな表示だったのが

good

この様にカラフルな表示になります。使い方はとても簡単で

package main

import (
    "github.com/mattn/go-colorable"
    "github.com/Sirupsen/logrus"
)

func main() {
    logrus.SetOutput(colorable.NewColorableStdout())

    logrus.Info("succeeded")
    logrus.Warn("not correct")
    logrus.Error("something error")
    logrus.Fatal("panic")
}

この様に NewColorableStdout を呼び出して io.Writer を取得し、それを logger 等に渡すだけです。Windows 以外の場合は os.Stdout を返す様になっているのでいちいち Windows かどうか判定する必要もありません。

UNIX で色を標準出力するライブラリ書いたけど、Windows... 知らねぇよ!って人は、ぜひこのライブラリを使ってみて下さい。きっと pull-request を貰うまでもなく、Windows 対応が完了している事になるはずです。

Posted at by