go modulesを使う
公式ドキュメントである"Using Go Modules"*1のまとめ
go moduleとは
go1.11から暫定的にサポートされている依存管理システムのこと。go1.13より前は環境変数を指定して有効にする必要があったが、go1.13から標準で使えるようになった。
go.mod
モジュールの"モジュールパス"と依存モジュールを定義するファイル。これが置かれてるディレクトリはモジュールパスのルートになる。go1.11からはカレントディレクトリか、それより親のディレクトリにgo.modが含まれている場合、$GOPATH/srcの外であってもgo modulesが有効になる。
モジュールの作成
$GOPATH/srcの外に適当にディレクトリを作る(/home/work/hoge
とする)。
とりあえずhello.goを作る。
hello.go
package hello func Hello() string { return "hello" }
テストを書く(hello_test.go)
package hello import "testing" func TestHello(t *testing.T) { want := "hello" if got := Hello(); got != want { t.Errorf("Hello() = %q, want %q ", got, want) } }
テストしてみる
$ go test PASS ok _/home/work/hoge 0.006s
goコマンドはインポートパスを知らないので、現在のパスに基づいて_/home/work/hoge
がインポートパスになっている。
次に、カレントディレクトリをモジュールにしてみる。
$ go mod init example.com/hello go: creating new go.mod: module example.com/hello
もう一度テスト。
$ go test PASS ok example.com/hello 0.006s
今度はモジュールパスになっている。
依存の追加
依存モジュールの最新版が欲しい
ソースコード中にimport somepackage
を書くだけで良い。go test
やgo build
した際、自動的に依存関係が解決され、そのモジュールの最新版が取得される。go.modには直接依存しているモジュールの情報が追記される。
package hello import "rsc.io/quote" func Hello() string { return quote.Hello() }
依存モジュールのバージョンを指定したい
go.modにrequire somepackage vX.Y.Z
のように指定する。
go.mod
module example.com/hello go 1.13 require rsc.io/quote v1.5.2
go.modには直接依存しているモジュールしか記載されない。全ての依存を確認するにはgo ilst -m all
を使う。
$ go list -m all example.com/hello golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c rsc.io/quote v1.5.2 rsc.io/sampler v1.3.0
go.sum
go.sumは依存モジュールのハッシュ値が記録されている。これにより、モジュールが意図せず変化した時に検出できるようになっている。 前述のgo.modとともにVCSに含めるのが良い。
olang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y= rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
依存モジュール名の変更
go.modにreplace
を書く。
相対パスでローカルのモジュールを指定できる。このようにすると、ソースコード中でimport "github.com/hoge/A"
としていても../home/bar/A
が参照される。
replace github.com/hoge/A => ../home/bar/A
リポジトリを指すことも出来るが、タグが必要。
replace github.com/hoge/A => github.com/bar/A latest
不要なモジュールの削除
$ go mod tidy
使われていないモジュールはこれで削除される。