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

最近は、PS4 でリメイクされた「バイオハザード2」をプレイしていて、グラフィックやシステムの進化に感動しています。
エンジニアの内山です。

今回は Go言語の 1.11 から標準で使えるようになった依存モジュール管理ツール Modules の使い方をご紹介します。

目次

Modules の機能

Modules は、依存モジュール管理ツールです。
Go言語 1.11 から標準で使えるようになりました。
以下のような機能を持っています。

  • 依存モジュールの自動検知
  • 依存モジュールのバージョン固定、バージョンアップ検知

依存モジュールの情報は go.modgo.sum という名前のファイルに記載されます。
これらのファイルを git などでバージョン管理することによって、依存モジュールとそのバージョンを明確にすることができます。

Ruby の Bundler や Node.js の npm のようなものですね。

Modules を使うには

Modules は、Go言語 1.11 以上のバージョンである必要があります。
1.11 以上をインストールすると、go mod コマンドが使えるようになります。

Modules を使う流れ

Modules を使う流れは以下のとおりです。

  1. go mod init で、初期化する
  2. go buildなどのビルドコマンドで、依存モジュールを自動インストールする
  3. go list -m all で、現在の依存モジュールを表示する
  4. go get で、依存モジュールの追加やバージョンアップを行う
  5. go mod tidy で、使われていない依存モジュールを削除する

実は go mod を直接実行することは少なく、他の go サブコマンドを実行したときに、自動的に処理が行われることが多いです。

以降は、コマンド実行例をご紹介します。
本記事では、バージョン 1.12 で動作確認しています。

1. go mod init で、初期化する

新規プロジェクトを作成して、 go mod init を実行します。
このコマンドには、引数としてモジュール名(example.com/go-mod-test)を指定します。

1
2
3
$ mkdir go-mod-test
$ cd go-mod-test
$ go mod init example.com/go-mod-test

go.mod ファイルが作成されます。
以下のように、指定したモジュール名が記載されています。

1
2
3
4
$ cat go.mod
module example.com/go-mod-test

go 1.12

2. go buildなどのビルドコマンドで、依存モジュールを自動インストールする

まずビルド対象となるプログラムを作成しておきます。
以下のプログラムを main.go という名前のファイルで保存します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 モジュールに依存している状態です。
ビルドコマンドを以下のように実行してみます。

1
2
3
$ go build
go: finding github.com/aws/aws-lambda-go/lambda latest
go: finding github.com/aws/aws-lambda-go/events latest

依存モジュールがインストールされている様子が出力されると思います。
go.mod の内容を見ると、依存モジュールの情報が記載されていることが確認できます。

1
2
3
4
5
6
$ 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 で、現在の依存モジュールを表示する

以下のように、現在の依存モジュールを確認してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ 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 をインストールしてみます。

1
2
$ go get github.com/golang/glog
go: finding github.com/golang/glog latest

以下のように go.mod ファイルにインストールしたモジュールの情報が追記されています。

1
2
3
4
5
6
7
8
9
$ 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 で、使われていない依存モジュールを削除する

以下のように、使われていない依存モジュールを削除してみます。

1
2
3
$ 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 の内容を確認してみます。

1
2
3
4
5
6
$ 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のときに、最初に依存モジュールをすべてインストールしたい場合があります。
その場合は、以下のコマンドで行なえます。

1
$ go get -u -t ./...

環境変数 GO111MODULE の設定

既存のプロジェクトが $GOPATH 内に存在する場合は、Modules を使うには、 以下のように環境変数を設定する必要があります。

1
$ export GO111MODULE=on

この設定を行わないと、以下のようなエラーが出ます。

1
2
$ 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 を作成することができます。

1
2
3
$ 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

このエントリーをはてなブックマークに追加