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

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

https://github.com/Songmu/goshim

プロジェクトでちょっとしたスクリプトを書いてリポジトリで共有したいとなった時に、スクリプト言語なら楽ですが、Goで書くのはやや面倒です。リポジトリを分けるようなものでもないし、わざわざ go install させるようなものでもないけど、ビルドしたバイナリをどこに置くのかなどが悩ましい問題です。macを使っている人もいればlinuxを使っている人もいるのでバイナリをリポジトリに配置するわけにもいきません。 go run でも良いかと思われるかもしれませんが、本当にちょっとしたものならよいいのですが、 go run は複数ファイルになった時のリストアップがめんどかったり、 go run は子プロセスを呼びだすのでプロセス管理がめんどかったり、コードが実行された場合、 os.Exit(2) とかしていても出力に出るだけで、終了コードが常に0になってしまうなどの問題があります。

そこで 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 してみてください。作ってみたら思いの外便利だったので、皆様も是非ご活用ください。

ところで、普通の go run で複数の.goファイルを指定する必要がある場合には、以下のようにするのが良いのかなーと思っているのですが、もっと良い方法があれば教えて下さい。もはや goshim があるのであまり関係ないのですが。

% go run $(go list -f '{{join .GoFiles " "}}') [args...]

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

created at
last modified at
comments powered by Disqus