ぺい

渋谷系アドテクエンジニアの落書き

direnvを使ってGo開発をいい感じにする

GOPATH以下が汚くなってません?

以下のような感じで、GOPATHを設定して開発をしていると・・・

export GOPATH=$HOME/go
export PATH=$PATH::$GOPATH/bin

ghqリポジトリを一括で管理しているので、探すのに困ることはありませんが f:id:tikasan0804:20171009150638p:plain

352個もソースがありました。こういうことをずっとしていると、自分の環境だけで動くみたいなソースになっていることに気づけなかったりします。あと、Goglandのindexing終わらない事案とか・・・w

また、仕様としてimportが以下のなるのですが、リポジトリ名やユーザーが変わると全滅するソースになったりします。一応GOPATHをプロジェクトごとに設定すれば解決出来ますが、それは正直面倒ですよね?それを解決してくれるのが、direnvです

package main

import "github.com/pei0804/direnv-example/sample"

func main() {
    sample.Sample()
}

やりたいこと

  • importを必要最低限だけ記述したい
  • 必要なパッケージだけをGOPATH以下に入れたい
  • GOPATHを動的にいい感じに設定したい
package main

import "app/sample"

func main() {
    sample.Sample()
}
package sample

import "fmt"

func Sample() {
    fmt.Println("Hello World")
}

最終的に上記のようなコードで動作させます。

direnvを使ってGOPATHをいい感じにする

github.com

direnv is an environment switcher for the shell. It knows how to hook into bash, zsh, tcsh and fish shell to load or unload environment variables depending on the current directory. This allows project-specific environment variables without cluttering the ~/.profile file.

つまり、シェルの環境変数いい感じ適用するぜ!

では、READMEにあるように、シェルそれぞれに合った設定をしてください。 自分はzshなので、以下の記述を追加しました。

# ~/.zshrc
eval "$(direnv hook zshrc)"

具体例

とりあえず動かす

$ git clone https://github.com/pei0804/direnv-example.git <--- あえてgit cloneで適当に配置する
$ cd direnv-example
$ make direnv                                                                                                                                                                                                                                                    
direnv allow
direnv: loading .envrc                                                                                                                                                                                                                                                      
direnv: export ~GOPATH
$ make run
go run main.go
Hello World

上記の手順で動いたと思います。 これでどこでも動かせる+必要なパッケージのみのクリーンな環境が出来ました。 ちなみにファイル構成は以下のような感じです。

.
├── LICENSE
├── Makefile
├── README.md
└── go
    └── src
        └── app
            ├── Makefile
            ├── main.go
            └── sample
                └── sample.go

シェルに設定していないGOPATHが正しく動作した理由は、.envrvの記述にあります。 内容は簡単なもので、今いる場所/go で新たなGOPATHを追加しているだけです。

export GOPATH=$(pwd)/go:$GOPATH

この操作で、さっき追加したソースはGoのルールに乗っ取り正しく構成されたソースになります。自分は最近この手法で開発するケースが増えています。特にDockerベースの開発をする時は、この手法がとてもマッチしてていい感じです。(また後日記事にします) ちなみに、最近いい感じになってきているgolang/depは、こういう構成で開発することを想定しているっぽいです。

ソース

github.com