おそらくはそれさえも平凡な日々

より良い `go run` を実現する goshim

https://github.com/Songmu/goshim

プロジェクトでちょっとしたスクリプトを書いてリポジトリで共有したいとなった時に、スクリプト言語なら楽ですが、Goで書くのはやや面倒です。リポジトリを分けるようなものでもないし、わざわざ go install させるようなものでもないけど、ビルドしたバイナリをどこに置くのかなどが悩ましい問題です。macを使っている人もいればlinuxを使っている人もいるのでバイナリをリポジトリに配置するわけにもいきません。

go run でも良いかと思われるかもしれませんが、本当にちょっとしたものならよいいのですが、以下の様な問題があります。

  • 複数ファイルになった時に go run main.go hoge.go とかやるのがダルい
    • (% go run $(go list -f '{{join .GoFiles " "}}') [args...] とかやる手はある)
  • 子プロセスを呼びだすのでプロセス管理がめんどい
  • os.Exit(10) とかしていても "exit status 10" とか出力に出るだけで、異常終了の場合、終了コードは常に1になってしまう
    • ※以前は終了コードが常に0だと書いてありましたが、mattnさんの指摘を受けて修正しました。またこの挙動は、Go1.7で修正予定 とのことです

そこで goshim の出番です。 goshim は指定したパッケージディレクトリのコードをビルドしてキャッシュし、それを exec で実行してくれます。それにより、 go build したバイナリを実行するのと同様にGoのソースを実行することができます。

以下のようにインストールします。

% go get github.com/Songmu/goshim/cmd/goshim

そして、以下のように呼び出します。

% goshim ./script/ore/pkg [args...]

これで、プロジェクトリポジトリに雑にGoのツールのソースコードを突っ込んでも、 goshim で雑に動かしてもらうことができるようになりました。

make のようにソースコードの mtime を見ているため、コードが更新されていない場合にはキャッシュが使いまわされ、高速に実行できる点もポイントです。

ビルドが必要であっても、ビルド自体に多少は時間はかかりますが、動き出してしまえばGoのバイナリを実行しているのと同じことになるので、ちょっとしたコードを雑にデプロイするのにも便利かもしれません。

go run main.go とかやるよりも goshim . の方が短いのも見逃せません。

実行にはgoの環境が必要であり、開発者のためのツールという感じなので、バイナリは提供しない予定です。普通に go get してみてください。作ってみたら思いの外便利だったので、皆様も是非ご活用ください。

goshimsyscall.Exec() を使っているので windowsで動きません。またmattnさんに怒られてしまいそうです。

created at
last modified at

2016-01-13T11:45:53+0900

comments powered by Disqus