GOPATH問題
$ cd ~/Documents/go/hoge
$ tree .
.
├── main.go
└── redis
├── redis.go
└── redis_test.go
$ cat main.go
package main
import (
"./redis"
)
func main() {
...
}
上記のようなmain.goのimport文はGoのお作法的にアウト。ただ、コンパイルも実行も可能。
お作法的には、import文にはgithub.com以下から記述するべき。
$ cat main.go
package main
import (
"github.com/kosuda/hoge/redis"
)
func main() {
...
}
上記のようなディレクトリ構成にするためには$GOPATH/src/github.com/kosuda/hogeにしなくてはいけない。
つまり、好きな場所にディレクトリ作って開発的なことは避けるべき
外部モジュールも含めてすべてGOPATH以下に含めるべき
そこで、なんかプロジェクトを管理する上でうまいやりかたないかなーと思い、以下調査結果。ついでに、依存関係の管理手法も。
ghq + direnv + godep
1. ghq
- インストールあんど設定
$ go get github.com/motemen/ghq
$ cat ~/.gitconfig
[ghq]
root = ~/.go/src
...
ghqをgo getしたらgitconfigにghq.rootを追加すればおk
- 使い方
$ ghq list
… <= ghq.root以下に含まれているリポジトリの一覧表示
$ ghq look ghq
cd /Users/a13486/.go/src/github.com/motemen/ghq
↑ ghq.root以下にあるディレクトリにcdできる。
ただ、ここで注意しなくてはいけないのが、ghq lookで移動するとシェルを再度実行するのでプロセスが増えるお。まぁそこまで気にすることはないんですが、僕は結構exitとかしてウィンドウ閉じることが多いのであれ?って感じになった。
理由は簡単。
#!/usr/bin/env bash
cd ~/test
ls
上記のようなスクリプトを実行しても~/testに移動しないのと一緒で~/testに移動するにはシェルを実行する必要があるのと一緒。
#!/usr/bin/env bash
cd ~/test
ls
/usr/bin/env bash
2.godep
- インストール
$ go get github.com/tools/godep
使ってみた。
$ tree .
.
├── README.md
├── main.go
└── redis
├── redis.go
└── redis_test.go
$ godep save
$ ls
Godeps/ README.md main.go redis/
$ ls Godeps/
Godeps.json Readme _workspace/
$ cat Godeps/Godeps.json
{
"ImportPath": "github.com/kosuda/benchmark",
"GoVersion": "go1.3",
"Deps": [
{
"ImportPath": "github.com/garyburd/redigo/redis",
"Rev": "6628c86d6a89ce7983c7c9b5e98c1df795fbd256"
}
]
}
おー、これで依存関係の管理がスッキリする。
ただし、これも注意しなくてはいけないのが必ず、以下の条件を満たすこと
+ VCSによって管理されていること
+ $GOPATH/src/{hosting service name}/{user name}/hogehogeという構成であること
3. 何がうれしい?
これで、ghq.rootにGOPATHを含めることで、ghq getで開発リポジトリを$GOPATHにもってきて開発みたいなことが可能。さらにgodepsがあるので、godeps getをそのリポジトリですれば自動で外部モジュールをインストできる。gpm (npmみたいな名前) というのもあったんだけど、godep saveみたいな自動で依存関係を抽出してファイルを作るというのが貧弱だったのでやめた。
4. うれしくないこと
どうしてもパッケージをすべてグローバルにインストするというのが気持ちわるい。それぞれのパッケージ内で管理してほしい。node_modules的なやつ。
5. direnv
brew install direnv
使い方とかは以下の記事が参考になった。
では、早速使ってみる
$ ghq look hoge
$ direnv edit .
direnv: loading .envrc
direnv: export ~GOPATH
$ cat .envrc
export GOPATH=$(pwd)/vendor/:$GOPATH
$ echo $GOPATH
vendor/が入っていることを確認
$ go get github.com/garyburd/redigo/redis
$ tree .
.
├── Godeps
├── README.md
├── main.go
├── redis
│ ├── redis.go
│ └── redis_test.go
└── vendor
├── pkg
└── src
└── github.com
└── garyburd
これでいい感じ。
以下、色々と確認作業。
$ rm -rf Godeps
$ godep save <= ちゃんとredigo/redisのやつがはいってる
$ rm -rf vendor
$ godep get <= vendorの中に入ってくれる
$ cd ..
$ echo $GOPATH
vendor/が外れて.zshrcに設定したGOPATHのみになっている
ということで、これでパッケージをそれぞれのプロジェクトで管理できるようになりました。ちなみに、direnvでgopathが変わってるときにghq getをしてもvendorには入らないのでgo getする。開発者が新たに追加するときに注意が必要。
ちなみに、Docker projectの場合
hack/make.shでvendor/:.gopath/src:$GOPATH的な感じで作って、srcのリンクを.gopath以下のとこに作り、hack/vendor.shで外部モジュールをvendorディレクトリにcloneしてくるみたいな作りで依存関係の管理をしてる模様。詳細はhack/packager.mdとかhack/vendor.shとかhack/make.shとか読めば分かる。まださらっと読んだだけなので間違ってるかも。
↑↑これは全然センスが感じられませんでした\(^o^)/