Go Modules入門

2022-04-09

Go Modules は、依存関係管理ツールです。
この記事では、Go Modules の概要と使い方を記載します。

概要

Go Modules (旧名 vgo)は Go v1.12 から正式リリースされている依存関係管理ツールです。
ここでは、その概要を記載します。

Minimal Version Selection

Go Modulesは Semantic Versioning に基づいてモジュールのバージョン管理を行ないます。

GOPATH mode と module-aware mode

Go Modulesは GOPATH modemodule-aware mode という2つのモードがあり、環境変数 GO111MODULE で切り替えることができます。

  • GO111MODULE=offGOPATH mode
  • GO111MODULE=onmodule-aware mode
  • GO111MODULE=auto$GOPATH/src 配下では GOPATH mode 、それ以外では module-aware mode で動作します

GOPATH mode と module-aware mode のそれぞれの特徴は以下の通りです。

GOPATH mode

go get コマンドで取得したモジュールは $GOPATH/src に保存されます。
標準 pkg 以外のモジュールはすべてここで管理されることになります。
go get コマンドで取得するモジュールは基本的に Github などのリポジトリで管理されており、$GOPATH/src 配下に git clone した形で保存されます。
モジュールのバージョンは、 git clone/pull したタイミングのバージョン( go1 タグ・ブランチもしくは master )や、 git checkout で変更した branches のバージョンになります。

モジュールのバージョンコントロールが面倒な点が、 GOPATH mode の難点です。

module-aware mode

go get コマンドで取得したモジュールは $GOPATH/pkg/mod に保存され、さらに、go.mod ファイルに記録され依存関係管理されます。
標準 pkg 以外のモジュールはすべてここで管理されることになります。
go get コマンドで取得するモジュールは基本的に Github などのリポジトリで管理されており、$GOPATH/pkg/mod 配下に Semantic Versioning された単位 で保存されます。
Semantic Versioning された単位は、 go.mod に記載されたモジュールのバージョンに対応します。
go.sum ファイルは依存モジュールのチェックサムの管理に利用されます。

従来通り $GOPATH 配下でプロジェクトを作成・開発し且つ module-aware mode を利用したい場合には GO111MODULE=on とする必要があります。
また、 $GOPATH 配下以外でプロジェクトを作成する場合であっても module-aware mode を利用すれば $GOPATH/pkg/mod 配下で依存モジュールが管理されるので、好きな場所で Go プロジェクトを作成することができます。

$GOPATH

$GOPATH 配下の構造がわからないとイメージつかないかもしれませんので、記載しておきます。

$GOPATH
├─bin/ # Goツール類の実行ファイルが格納されるディレクトリ
├─pkg/ # ビルドしたパッケージオブジェクトが格納されるディレクトリ
│  ├─darwin_amd64/
│  │ ├─github.com/
│  │ │  └─GitHubアカウント名
│  │ │    ├─`*.a`ファイル[^1]
│  │ │    └─GitHubレポジトリ名/`*.a`ファイル[^2]
│  │ └─pkg.in/
│  │   ├─パッケージ名/
│  │   └─`*.a`ファイル
│  │
│  └─mod/ # Go Modules で取得したモジュール類が格納されるディレクトリ
│    ├─cache/      # download したモジュール類のメタ情報や実態のzipなどのキャッシュ
│    ├─github.com/ # Github リポジトリから取得したモジュール
│    │ └─GitHubアカウント名
│    │    └─GitHubレポジトリ名@バージョン/ # この「@バージョン」部分でバージョンを識別して管理している
│    └─gopkg.in/   # gopkg.in リポジトリから取得したモジュール
└─src/ # GOPATH mode: パッケージごとのソースコードを配置するディレクトリ
  ├─gopkg.in/
  │  └─パッケージ名/
  │    └─LICENSEとか`*.go`とかREADMEとか
  └─github.com/
    ├─GitHubアカウント名
    │  └─GitHubレポジトリ名/
    │    └─LICENSEとか`*.go`とかREADMEとか
    └─<あなたのGitHubユーザ名> # Go Modules OFF の場合
      └─GitHubレポジトリ名/ # プロジェクトディレクトリ(複数)
        ├─go.mod
        ├─go.sum
        ├─main.go
        └─その他、あなたが開発中のソフトウェアのコード

使い方

ここでは Go 1.16 以降前提に記載します。

go.mod の作成

go mod init を使用して、作成するプロジェクトのリポジトリを指定します。
Go で作成するプロジェクトは Github などのリポジトリ管理されることが前提で考えられているためです。

$ go mod init github.com/pepese/golang-gin-sample

なお、 GOPATH 配下で go mod init する場合、自明なのでリポジトリを省略することができます。

$ mkdir -p $GOPATH/src/github.com/<あなたのGithubアカウント名>
$ cd $GOPATH/src/github.com/<あなたのGithubアカウント名>
$ mkdir <golangプロジェクト> # プロジェクトディレクトリの作成
$ cd <golangプロジェクト>
$ export GO111MODULE=on
$ go mod init              # `GO111MODULE=on go mod init` のように一行でも
go: creating new go.mod: module github.com/<あなたのGithubアカウント名>/<golangプロジェクト>

go mod init が完了すると go.mod が作成されています。

go.mod/go.sum の更新

Go 1.15 までは go buildgo test などのコマンドで go.mod/go.sum の内容が勝手に更新されていましたが, 1.16 からは自動では更新されなくなっています。
そのため、何らかの拡張機能を有したコードエディタ上の import で新しいモジュールを追加しても go.mod/go.sum に追加されない場合があります。
さらに利用のないモジュールが残ったりした場合なども含めて、 go.mod/go.sum を最適化するために以下のコマンドを利用しましょう。

$ go mod tidy

なお、上記ではモジュールのバージョンは最新化されません。
go get を使って go.mod/go.sum に記述されているモジュールのバージョンを変更しましょう。

$ go get golang.org/x/tools/gopls@v0.6.5

バージョン番号サフィックスが有効になっており、 @latest なども利用できます。

go install/get

go install/get の違いは以下の通りです。

  • バイナリのビルドとインストールのための go install
  • go.mod 編集のための go get

ツールの導入は go installgo.mod の編集は go get というふうに使い分けましょう。

go.mod

go.mod では以下のディレクティブが使用されます。

ディレクティブ 説明
module module github.com/pepese/golang-gin-sample モジュール名、 go mod init で指定したリポジトリ
go go 1.17 有効な Go のバージョン
require require other/thing v1.0.2 インポート・モジュール
exclude exclude old/thing v1.2.3 除外モジュール
replace replace bad/thing v1.4.5 => good/thing v1.4.5 モジュールの置換
retract retract v1.0.5 撤回バージョン

go ディレクティブの更新

Go のバージョンを変更したい場合は以下のコマンドを実行してください。

$ go mod tidy -go=1.17

おすすめ書籍

おすすめ記事