2012/12/13


Go Playground で time パッケージが有効になった。
Go Playground

The Go Playground is a web service that runs on golang.org 's servers. The serv...

https://play.golang.org
公式発表
Time - Google Groups
https://groups.google.com/d/topic/golang-nuts/JBsCrDEVyVE/discussion
\x0c というコードを fmt.Print() で出力するとクリアされ、fmt.Print()fmt.Println() を使って文字列を出力、time.Sleep を使ってアニメーション表示が出来る様になります。
こういうの出来たら、これを試さない訳にはいかない!!!
Go Playground
http://play.golang.org/p/NOycgN2i6b
goplayground
皆さんも面白いの作ってみて下さい。
Posted at by



2012/12/04


以前、こんな記事を書いた。
Big Sky :: 日本語grepが出来るjvgrepというのを作った。
http://mattn.kaoriya.net/software/lang/go/20110819203649.htm
実は jvgrep を作った当初、処理がかなり遅かった。まぁ複数のエンコーディングを試すからしょうがないよね程度に思ってたけど、どうにか速くならないかと思い、処理の並行化を行ってパフォーマンスを向上させた。この記事はその時にやった改善策。

jvgrep は -R オプションや **/* で再帰検索する機能が付いているんだけど、これを行う場合
  • find
  • grep
という処理が走る事になる。 しかしながら結果の順番を守ろうと考えた場合、find と grep を安直に同時に走らせる訳にはいかなくなる。走らせると結果が交錯してしまうからだ。
こういうのを行う場合、C言語だとFIFOキューとスレッドを作り、find 側が push、grep 側が pop を行う仕組みを作る。
しかしながらメモリの増加を管理したり、grep 側が空きになった時に待機する処理ってのを考えると、C言語だと結構めんどくさかったりする。

Go言語はこのあたりが非常に簡単に実装出来る様になっている。

まず find 部と grep 部の処理を分割し、grep 部を FIFO キューに対して連続で呼び出せる様にする。 func GoGrep(ch chan *GrepArg, done chan int) {
    for {
        arg := <-ch
        if arg == nil {
            break
        }
        Grep(arg)
    }
    done <- 1
}
Grep が本体だが今回の話の本質ではないので省略。引数の ch に Grep が使う引数が飛び込んで来る。全ての grep 対象が完了するか途中終了する場合には find 側から nil を渡すというお約束にした。
メインコントローラ側で、この FIFO となるチャネルを作る。 ch := make(chan *GrepArg)
done := make(chan int)
なぜ二つチャネルを作っているかというと、find 側が先に終了してしまった場合にプログラムが終了しない様、待機する為で、上記の GoGrep の最後に 1 を渡している。 チャネルを作ったら GoGrep をバックグラウンドで起動する。 go GoGrep(ch, done)
Go言語は関数呼び出しに go を付けるだけで非同期に実行してくれる。
次に find 部。Go言語の filepath パッケージにはファイルが見つかる度にコールバック関数を呼び出してくれる Walk がある。
filepath.Walk(root, func(path string, info os.FileInfo, err errorerror {
    if info == nil {
        return err
    }

    // 以下 path に対する処理を行う。
    path = filepath.ToSlash(path)

    // 検索対象外のパスにマッチする場合
    if ere != nil && ere.MatchString(path) {
        // ディレクトリならば SkipDir を返して他のフォルダに移る
        if info.IsDir() {
            return filepath.SkipDir
        }
        // ファイルならば以下の処理は行わない
        return nil
    }

    // ... 省略 ...

    // 検索対象のファイルならば
    if fre.MatchString(path) {
        // GoGrep が待っているチャネルにパラメータを渡す
        ch <- &GrepArg{pattern, path, /* ... 省略 ... */}
    }
})
検索対象のファイルが見つかった場合、先ほど作成した ch に Grep 引数を渡している。
find 側は全てのファイルを検索し終えたら grep 側に処理の終了を伝える。 ch <- nil
そして grep の終了(done)を待つ。 <-done
図解すると
jvgrep
こんなイメージになる。find もフォルダを再帰的に検索すると結構重くなるので各処理を並行実行させる事でかなりのパフォーマンス向上が得られた。

最初から find 部と grep 部が関数分けされていれば、もっと簡単に並行処理の実装が出来た事になる。
Posted at by



2012/11/19


redmineをwebで使っていると色々とイライラする事が多く、どうしてもコマンドラインから操作したくなった。
しかしコマンドラインから redmine を操作できる物で気に入った物が無かったのでGo言語で自作するに至った。まずライブラリ
mattn/go-redmine - GitHub
https://github.com/mattn/go-redmine
残念ながら API は全て出揃ってなくて対応状況は以下の様な感じ。
API Implements
Issues 100%
Projects 100%
Project Memberships 100%
Users 0%
Time Entries 100%
News 100%
Issue Relations 100%
Versions 0%
Wiki Pages 0%
Queries 0%
Attachments 0%
Issue Statuses 100%
Trackers 100%
Enumerations 100%
Issue Categories 100%
Roles 100%
Groups 0%
とりあえず issues 関連は出来てるので、これを使うコマンドラインプログラムを書いた。 $ go get github.com/mattn/go-redmine/godmine 名前は中二病っぽいけど「godmine」という名前にした。
使い方は、例えば issue の一覧であれば $ godmine issue list もしくは $ godmine i l issue の登録は $ godmine issue create "なんてこった" "大変だ!" みたいにするか $ godmine issue append で起動するテキストエディタ(環境変数EDITORを参照しunix改行コードが扱えるテキストエディタのみ使用可能)で ### Subject Here ###
### Description Here ###
上記の部分を書き換えて保存終了する。
設定ファイルは ~/.config/godmine/settings.json に(Windows では %APPDATA%/godmine/settings.json) {
    "endpoint""http://redmine.example.com",
    "apikey""アクセスキー",
    "project"1
}
の様に書く。Project Id は URL から調べて下さい。なお、環境変数 GODMINE_ENV を「foo」に設定すると「settings.foo.json」が読まれるので、複数のプロジェクトを扱う場合は $ GODMINE_ENV=foo godmine issue append とうい感じに使える。以下現状サポートしてるコマンド
gotmine [arguments]

Project Commands:
  add      a create project with text editor.
             $ godmine p a

  create   c create project from given arguments.
             $ godmine p c name identifier description

  update   u update given project.
             $ godmine p u 1

  show     s show given project.
             $ godmine p s 1

  delete   d delete given project.
             $ godmine p d 1

  list     l listing projects.
             $ godmine p l

Issue Commands:
  add      a create issue with text editor.
             $ godmine i a

  create   c create issue from given arguments.
             $ godmine i c subject description

  update   u update given issue.
             $ godmine i u 1

  show     s show given issue.
             $ godmine i s 1

  delete   d delete given issue.
             $ godmine i d 1

  close    x close given issue.
             $ godmine i x 1

  notes    n add notes to given issue.
             $ godmine i n 1

  list     l listing issues.
             $ godmine i l

Membership Commands:
  show     s show given membership.
             $ godmine m s 1

  list     l listing memberships of given project.
             $ godmine m l 1

User Commands:
  show     s show given user.
             $ godmine u s 1

  list     l listing users.
             $ godmine u l
管理者権限があればプロジェクトを消す事も出来ます。なんて怖い!
issue の close(x) は、ステータス一覧の先頭から見て close にチェックされている最初のステータスで issue を閉じます。
元はと言えば Windows で ruby の動作が遅すぎるのが嫌で作り始めましたが、linux でも動きます。

まだ作り始めたばかりなので、欲しい機能があれば入れていくつもりです。


Posted at by