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

## 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`)を指定します。

```bash
$ mkdir go-mod-test
$ cd go-mod-test
$ go mod init example.com/go-mod-test
```

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

```bash
$ cat go.mod
module example.com/go-mod-test

go 1.12
```


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

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

```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` モジュールに依存している状態です。
ビルドコマンドを以下のように実行してみます。

```bash
$ go build
go: finding github.com/aws/aws-lambda-go/lambda latest
go: finding github.com/aws/aws-lambda-go/events latest
```

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

```bash
$ 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` で、現在の依存モジュールを表示する

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

```bash
$ 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` をインストールしてみます。

```bash
$ go get github.com/golang/glog
go: finding github.com/golang/glog latest
```

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

```bash
$ 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` で、使われていない依存モジュールを削除する 

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


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

```bash
$ 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 を使う流れでした。


## 参考


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