注:古い記事の為、内容が最新ではない可能性がありますm(_ _)m
Google App Engine for GoでのGOPATH設定についていろいろ試行錯誤したのでメモしておきます。 ベストプラクティスかどうかは分かりません。
わるいGOPATH
まず、今迄ずっとやっていて相当ストレスを感じていた悪いGOPATH設定を晒しておきます。
GAEアプリケーション単位でワークスペース(参考:How to Write Go Code - The Go Programming Language)ディレクトリを作成し、そこをGOPATHに設定していました。
hello <- GOPATHはここに設定 + src + app.yaml + hello.go
この状態でgoapp getすると、取得してきた3rd partyライブラリはapp/srcの下に入ります。
hello + src + github.com <- ここにgoapp getされる + somelibs + app.yaml + hello.go
そうすると、以下の困ったことが起きます。
- ライブラリをリポジトリ単位で取ってきてしまう(回避するoptionとかあるのかも)為、巨大なライブラリ群だと不要なコードまで取得される。
- GAE/Goはアプリケーションディレクトリ以下のgoコードを全てコンパイルする仕様の為、ビルド時間が長くなる。Goの魅力半減(´・ω・`)
- 不要なコード中に別のライブラリ依存があった場合、不要なのにそれもgoapp getしないとビルド通らない。
- 不要なコード中でGAEで使えないpackage(syscall, unsafe, etc)が使われていた場合、deployできない。深刻!!
よいGOPATH
GOPATHを、どこでもよいですがアプリケーションディレクトリの外に設定します。
例↓
hello + gopath <- GOPATH + src + github.com <- ここにgoapp getされる + somelibs + app <- アプリケーションディレクトリ + app.yaml + hello.go
アプリケーションディレクトリにはGOPATH設定する必要はありません。
こうすると、goapp getはリポジトリ毎ごっそりGOPATH/srcに取得しますが、ビルド時には必要なパッケージのみ参照してくれる様になります。 GOPATH内でGAE使用不可なパッケージが使用されていてもビルド可能です。※実際にはパッケージディレクトリ単位で参照している様なので、使用したいパッケージにGAE使用不可なコードが含まれている場合はビルド出来ません。
なお、この様にGOPATHを別にした場合、ローカル開発サーバー起動時にはGOPATH内のコードに対してGAE不正importチェックが働きません(SDK1.9.15現在)。なのでローカルではsyscallパッケージとか普通に実行出来たりします。deploy時にはチェックが働いてエラーになるので注意して下さい。
GAEではない通常のGo開発用にすでにGOPATHを設定していて、GAEでの開発でもそれを共有したい場合はそのままでOKです。
何らかの理由でアプリケーションディレクトリにもGOPATHを設定したい場合は、コロン(windowsはセミコロン)で区切って両方設定できます。goapp get
は先頭のGOPATHにインストールしますのでライブラリ用GOPATHを先頭に設定しましょう。
その他GOPATH
GOPATHが設定されない場合、goappコマンドにより自動でGOPATHが設定されます。
appengine sdkの場合
<sdk root>/gopath
<sdk root>/platform/google_appengine/gopath
設定されているGOPATH以下のコマンドで確認できます。
goapp env GOPATH
appengine SDKのgopathは、SDKのバージョン上げたらコピーするかgoapp getしなおさないとダメそうですね(未確認)。
cloud sdkの方はバージョン上げても引き継いでくれそうです(未確認)。
参考資料:
- GOPATHについて
How to Write Go Code - The Go Programming Language
- GAE/GoでのGOPATHサポートについて