Go言語の依存モジュール管理ツール Modules の使い方

最近は、PS4 でリメイクされた「バイオハザード2」をプレイしていて、グラフィックやシステムの進化に感動しています。
エンジニアの内山です。
今回は Go言語の 1.11 から標準で使えるようになった依存モジュール管理ツール Modules の使い方をご紹介します。
目次
Modules の機能
Modules は、依存モジュール管理ツールです。
Go言語 1.11 から標準で使えるようになりました。
以下のような機能を持っています。
- 依存モジュールの自動検知
- 依存モジュールのバージョン固定、バージョンアップ検知
依存モジュールの情報は go.mod
と go.sum
という名前のファイルに記載されます。
これらのファイルを git などでバージョン管理することによって、依存モジュールとそのバージョンを明確にすることができます。
Ruby の Bundler や Node.js の npm のようなものですね。
Modules を使うには
Modules は、Go言語 1.11 以上のバージョンである必要があります。
1.11 以上をインストールすると、go mod
コマンドが使えるようになります。
Modules を使う流れ
Modules を使う流れは以下のとおりです。
go mod init
で、初期化するgo build
などのビルドコマンドで、依存モジュールを自動インストールするgo list -m all
で、現在の依存モジュールを表示するgo get
で、依存モジュールの追加やバージョンアップを行うgo mod tidy
で、使われていない依存モジュールを削除する
実は go mod
を直接実行することは少なく、他の go サブコマンドを実行したときに、自動的に処理が行われることが多いです。
以降は、コマンド実行例をご紹介します。
本記事では、バージョン 1.12
で動作確認しています。
1. go mod init
で、初期化する
新規プロジェクトを作成して、 go mod init
を実行します。
このコマンドには、引数としてモジュール名(example.com/go-mod-test
)を指定します。
$ mkdir go-mod-test
$ cd go-mod-test
$ go mod init example.com/go-mod-test
go.mod
ファイルが作成されます。
以下のように、指定したモジュール名が記載されています。
$ cat go.mod
module example.com/go-mod-test
go 1.12
2. go build
などのビルドコマンドで、依存モジュールを自動インストールする
まずビルド対象となるプログラムを作成しておきます。
以下のプログラムを main.go
という名前のファイルで保存します。
package main
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return events.APIGatewayProxyResponse{}, nil
}
func main() {
lambda.Start(handler)
}
このプログラムでは、AWS Lambda のハンドラを実装しているので、aws/aws-lambda-go
モジュールに依存している状態です。
ビルドコマンドを以下のように実行してみます。
$ go build
go: finding github.com/aws/aws-lambda-go/lambda latest
go: finding github.com/aws/aws-lambda-go/events latest
依存モジュールがインストールされている様子が出力されると思います。
go.mod
の内容を見ると、依存モジュールの情報が記載されていることが確認できます。
$ cat go.mod
module example.com/go-mod-test
go 1.12
require github.com/aws/aws-lambda-go v1.13.2
3. go list -m all
で、現在の依存モジュールを表示する
以下のように、現在の依存モジュールを確認してみます。
$ go list -m all
example.com/go-mod-test
github.com/BurntSushi/toml v0.3.1
github.com/aws/aws-lambda-go v1.13.2
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d
github.com/davecgh/go-spew v1.1.0
github.com/pmezard/go-difflib v1.0.0
github.com/russross/blackfriday/v2 v2.0.1
github.com/shurcooL/sanitized_anchor_name v1.0.0
github.com/stretchr/objx v0.1.0
github.com/stretchr/testify v1.4.0
github.com/urfave/cli v1.22.1
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
gopkg.in/yaml.v2 v2.2.2
本プロジェクトで直接依存しているモジュールだけでなく、依存モジュールが依存しているモジュールもすべて出力されています。
4. go get
で、依存モジュールの追加やバージョンアップを行う
試しにログ出力のための golang/glog
をインストールしてみます。
$ go get github.com/golang/glog
go: finding github.com/golang/glog latest
以下のように go.mod
ファイルにインストールしたモジュールの情報が追記されています。
$ cat go.mod
module example.com/go-mod-test
go 1.12
require (
github.com/aws/aws-lambda-go v1.13.2
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
)
// indirect
というコメントは、直接依存しているモジュールではないことを表しています。
先程作成したプログラムでは、まだ golang/glog
を使用していないので、このようなコメントが追記されています。
5. go mod tidy
で、使われていない依存モジュールを削除する
以下のように、使われていない依存モジュールを削除してみます。
$ go mod tidy
go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
go: extracting gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
go.mod
の内容を確認してみます。
$ cat go.mod
module example.com/go-mod-test
go 1.12
require github.com/aws/aws-lambda-go v1.13.2
先程インストールした golang/glog
が使われていないので、その情報が削除されている状態になっています。
以上、Modules を使う流れでした。
落穂拾い
あらかじめすべての依存モジュールをインストールしたい場合
CI/CDのときに、最初に依存モジュールをすべてインストールしたい場合があります。
その場合は、以下のコマンドで行なえます。
$ go get -u -t ./...
環境変数 GO111MODULE の設定
既存のプロジェクトが $GOPATH 内に存在する場合は、Modules を使うには、 以下のように環境変数を設定する必要があります。
$ export GO111MODULE=on
この設定を行わないと、以下のようなエラーが出ます。
$ go mod init
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'
dep からの移行
Modules 以前は、dep を使っている場合も多いと思います。
go mod init
コマンドは、Gopkg.lock を読み込んで、go.mod
を作成することができます。
$ GO111MODULE=on go mod init
go: creating new go.mod: module hogehoge
go: copying requirements from Gopkg.lock
参考
Modules
https://github.com/golang/go/wiki/Modules
Go & Versioning
https://research.swtch.com/vgo
Using Go Modules
https://blog.golang.org/using-go-modules