go 1.11のmodules(vgo)が有効な環境で相対importが cannot find module for path でエラーになった話。
vgoが有効な環境の場合に相対importがエラーになる
時折、GOPATH外で作業したりするときなどに相対importが使いたくなる。例えば以下の様な構成でxxx packageの関数を利用したい。
. ├── main.go └── xxx └── hello.go 1 directory, 2 files
xxx/hello.go
package xxx import "fmt" // Hello : func Hello() { fmt.Println("hello") }
main.go
package main import ( "./xxx" ) func main() { xxx.Hello() }
以前まではGOPATH外で書いたgoのコードでファイルを分けたpackageを読み込んで利用したいときには、このような形で相対importを使うことができた。一方でgoのmodules(vgo)が有効な環境では上手くpackageを探すことができずにエラーになる。具体的には以下の様なエラー。
go run 00*/main.go build github.com/podhmo/<mypkg>/00ng: cannot find module for path _$HOME/venvs/my/<mypkg>/00ng/xxx
対応方法
対応方法は2つある。1つはmodullesを無効にする方法。もう一つはgo.modを書く方法。
modulesを無効にする方法
wikiによると、GO111MODULE
という環境変数に値を設定することで有効・無効を指定できる(defaultはauto)。
$ GO111MODULE=on # 有効 $ GO111MODULE=off # 無効
なので、暫定的な対応としては以下の様な形で無効にして呼んであげれば良い。
$ GO111MODULE=off go run 00*/main.go hello
go.mod
もう一つの方法はmodulesの機能を使って解決する方法。
# go.modを作成する(package名はmainでも何でも良い) $ go mod init m
go.mod
module m
以下のように書き換える(mはgo.modで指定したpackage名)
--- 00ng/main.go 2018-12-26 07:15:18.837219706 +0900 +++ 01ok/main.go 2018-12-26 07:31:33.159657145 +0900 @@ -1,7 +1,7 @@ package main import ( - "./xxx" + "m/xxx" )
相対的な位置ではなく、mというpackageのsub packageという意味(ここでmはgo.modで指定したpackage名)。
今度は大丈夫
$ go run main.go hello
こちらの方法の方が筋が良さそう。go modulesでGOPATHから解放されようとしている感じなので(全てのimport pathに完全修飾で指定するという世界観)。
実際の所goのrepositoryでもissueがあげられていて、そのissueの中では、残念だけれど想定通りの挙動で、相対import自体が古いgoでの半ば場当たり的に付けられた機能という返答がされている。