電気ひつじ牧場

技術メモと日常のあれこれ

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 testgo 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

使われていないモジュールはこれで削除される。