概要
ローカルのパッケージをインポートする際にはまったのでメモ。
結論
先に結論から書くと、
GOPATH配下にインポートしたいパッケージを配置して、go.modのreplaceでプロジェクトディレクトリのgo.modとリンクさせる必要がありました。
やりたいこと
mainパッケージから別パッケージをインポートして使いたい。
例えば、以下のようなディレクトリ構成で、main.goからfirst_module.goをインポートして使う。
work/
├── main.go
└── modules
└── first_module.go
数値を渡したら合計値を計算して返す、といった内容で作ります。
package main
import (
"fmt"
)
func main() {
sl := []int{10, 20, 30}
r := modules.Calculate(sl...)
fmt.Println(r)
}
package modules
func Calculate(i ...int) int {
var num int
for _, v := range i {
num += v
}
return num
}
(goのバージョンは以下です。)
go version go1.15.2
解決までの過程
上記の構成のままでは、以下のエラーとなりfirst_module.goはインポートできません。
import (
"fmt"
"./modules"
)
could not import ./modules (no required module provides package "./modules")
go.modを作っていなかった...
ということで作成します。
go mod init work
GOPATH配下にインポートしたいモジュールをコピーして、requireで指定します。
moduleには、プロジェクトのモジュール名を記載します。
require github.com/work/modules
module work
go 1.15
go.modを作成したので、一度実行してみます。
$ go run main.go
go: errors parsing go.mod:
/work/go.mod:1: usage: require module/path v1.1.1
どうやらモジュールにバージョンを付与しないと行けないようなので、追記します。
require github.com/work/modules
再度実行してみますが、unknown revisionとか言われます。
$ go run main.go
go: github.com/work/modules@v1.1.1: reading github.com/work/modules/go.mod at revision v1.1.1: unknown revision v1.1.1
GOPATH配下にインポートするモジュールを作成するだけではダメで、
以下のようにreplaceで、プロジェクトディレクトリにリンクさせないといけないようです。
require github.com/work/modules v1.1.1
replace github.com/work/modules => ./modules
module work
go 1.15
これでOKと思いきや、以下のエラーに。
インポートするモジュールを置いているディレクトリにもgo.modを作成する必要がありました。
$ go run main.go
go: github.com/work/modules@v1.1.1: parsing modules/go.mod: open /work/modules/go.mod: no such file or directory
ということで、go.modを作成し再度実行。
$ go run main.go
60
うまく行きました。
最終的なディレクトリ構成は以下のようになりました。
work/
├── go.mod
├── main.go
└── modules
├── first_module.go
└── go.mod
【備考】 Go modules(vgo)について
基本的に、プロジェクトディレクトリはGOPATH配下に作成しないといけない、と思っていましたが、
go1.11からGo modules(vgo)が標準装備となり、すべてGOPATH配下に配置しないといけないということはなくなりました。
go.modをプロジェクトルートに配置することでvgoモードで動作し、自分の好きなところにプロジェクトを作成できます。
vgo:
モジュール管理ツール。go.modファイルで依存モジュールやバージョンを管理する。
go.mod:
node.jsでいうpackage.jsonのようなイメージ。
go envでGO111MODULE=onにすることでGo modules(vgo)が有効になります。
(-w オプションを付けて環境変数を設定)
$ go env -w GO111MODULE=on
$ go env
GO111MODULE="on"
※ なお、go 1.13以降は、GO111MODULE=onにしなくてもデフォルトで有効な状態になっています。