お世話になっております。
しゃまとんです。

先日、Go1.5から1.6にアップデートしたときのあれこれという記事を書きまして、 vendorがいいねと思っていたのですが、どんな仕組みで参照しているんだろうともやもやしたので挙動を少し確認してみました。

ちなみに検証が結構ながいので、先にまとめっぽことを書いておくと…


${GOPATH}/src/{package}内に存在するコードhoge.goのビルド時に、自分の位置からvendorを検索し、 見つからなかったら上位層でのvendorを探す。最終的にはsrc/vendorまで検索する。

ただし、検索は他のGOPATHや上位層に存在する他ディレクトリまでは見に行かない。

また、src直下にコードをおいてbuildしてもsrc/vendorは参照しようとしない。 (そもそもそこにコードは配置される想定ではないと思われる)


かなと思います。
では以下検証です。

わかっていることとして、vendorフォルダがあると配下のパッケージが簡単にimportできるということだったので、 下記のようにディレクトリとコードを配置しました。色々なところに空のvendorフォルダを作成してどうなるか確認します。

その前に、コードですが以下の様な感じです。vendor配下にあるであろうprintパッケージを呼び出すようなテストコードです。

■ test.go

package main

import "print"

func main() {
  print.Hello()
}

■ vendor/print/print.go

package print

import "fmt"

func Hello() {
  fmt.Println("hello!!")
}

■ 何もない状態
1. go run src/hoge/fuga/test.go(GOPATH未定義)
GOPATHが無いので、エラーになります。vendorに関する表示もなし。

そこでGOPATHを下記のように設定します。

export GOPATH=~/vendor_check

2. go run src/hoge/fuga/test.go
実行すると、vendorが表示されるようになります。ただpiyoは検索対象にはならないようです。どうやら実行するファイルから上に辿って検索するっぽい。

3. go run src/test.go
src/vendorが表示されるのかと思ったら、何もでませんでした。

4. go run lib/src/hoge/fuga/test.go
そもそも、GOPATHの定義外なのでダメなようです。

そこでGOPATHを追加します。

5. go run lib/src/hoge/fuga/test.go
vendorの表示がでるようになりました。こちらではlib/src/vendorまで見ているようです。src/は見ないようですね。

6. go run lib/src/test.go
src/test.goと同じでvendorは出ません。

7. go run lib/hoge/fuga/test.go
やはり、どこかしらのsrc配下にないとダメなようですね。

8. go run test.go
当然なにも出ません。

全体的に確認したのでprintを有効にします

9. go run src/hoge/fuga/test.go
helloと表示されました。ちゃんと参照できていますね。

10. go run src/test.go
こちらは参照できませんでした。src直下は想定外っぽい・・・?

src直下は利用するべきではないようですね。
実行できるっぽいlib/src配下もダメなよう。(vendor配下に配置すればいけます)
挙動からするとGOPATH/src配下で自分が関係している上位層のvendorまで探しに行くようです。

これからするとGOPATHは複数にせず、1つのsrc内で完結させるのがよさそうですね。
以上です。