76
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Go: DepからGo Modulesへの移行

Last updated at Posted at 2019-11-30

はじめに

Go modulesはGo1.13(August 2019)から正式に導入されたGo言語公式の依存パッケージ管理ツールです。Go modules以前は、depが依存パッケージ管理のツールとしてはデファクトでした。Go modulesはGo1.11から使用は可能でしたが、環境変数(ENV GO111MODULE=on)を設定したり色々と手間がかかる事前準備が必要でした。Go1.13からはデフォルトでGo modulesが組み込まれています。

そもそもGo Modulesとは何?

Goの新しい依存管理システムである。
モジュールは、一つのユニットとしてバージョン管理されている関連Goパッケージの集まり。1.11からはmoduleモードとGOPATHモードが使えるようになっていましたが、1.13からはmoduleモードがデフォルトでONになっています。Goのオープンソースモジュールのエコシステムをより良く活用できるように、moduleモードがデフォルトで動作するようにしているそうです。
Golang.org: modules
Golang.org: Wiki-Modules

モジュールとは

モジュール対応モードでは,標準ライブラリを除くパッケージを「モジュール(module)」として管理する。 パッケージが git 等のバージョン管理ツールで管理されている場合はバージョン毎に異なるモジュールと見なされる。 つまりモジュールの実体は「パッケージ+バージョン」ということになる。
ただしコード上ではパッケージとモジュールの間に区別はなく,したがってソースコードを書き換える必要はない。 モジュールはソースコードではなくgo.modファイルで管理される。

depとGo Modulesの機能差マトリクス

項目 dep go modules
実行する場所 GOPATH以下である必要がある *Goプログラムのルートディレクトリ
*GOPATH以下にあるソースコードでもgo.modファイルがあればモジュール対応モードで管理が可能
管理ファイル Gopkg.tomlGopkg.lock go.modgo.sum
Vendoring depがvendoring対応のツール go mod vendorというコマンドでvendoring対応ができる dockerの場合はvendoring利用がおすすめ
Gitでの管理 Gopkg.tomlGopkg.lockをGit管理する 通常は、go.modgo.sumは共にGit管理する
パッケージ管理 リポジトリの最新リビジョンのみが対象 リポジトリのバージョンタグまたはリビジョン毎に管理。Semantic Versioningに対応 Semantic Versioningとは、vX.X.Xというようなバージョン番号の定義方法
依存packageの場所 $GOPATH/src以下プログラムルートのvendorディレクトリ $GOPATH/pkg/mod以下 *go modで取得したバイナリなどは$GOPATH/pkg/mod/以下にキャッシュされている
*CIの高速化でビルドキャッシュをするときはこのディレクトリをキャッシュする必要がある
*キャッシュを削除するときはgo clean -cacheコマンドで削除
*go mod vendorコマンドでdepのようにvendorディレクトリに依存関係を保存することができる
*go mod tidyでgo.modから不要な依存関係を削除

パッケージ管理で、GOPATHの依存がなくなる点くらいで双方の機能差はほぼ無し。
「$GOPATHの呪縛からの解放」という最大のメリットで、何よりも代えがたいポイントのように思えます。

GOPATHモード(GOPATH mode)とモジュールモード(module-aware mode)

バージョン1.11以降からは、Go言語コンパイラは以下の2つのモードのどちらかで動作するようになっていました。

モード
GOPATHモード バージョン 1.10 までの動作モード。標準ライブラリを除く全てのパッケージの管理とビルドを $GOPATH 以下のディレクトリで行う。パッケージの管理はリポジトリの最新リビジョンのみが対象となる
モジュール対応モード 標準ライブラリを除く全てのパッケージをモジュールとして管理する。モジュールの管理とビルドは任意のディレクトリで可能で,モジュールはリポジトリのバージョンタグまたはリビジョン毎に管理される

環境変数 $GO111MODULE

モード切替は$GO111MODULEという環境変数で切り替えます。1.12でもautoが規定値になっている。 1.13でも引き続きautoになっていますが、現在の作業ディレクトリにgo.modファイルが含まれる場合は、goコマンドのモジュール対応モードがアクティブになります。
リリースノート:1.13

設定値

設定値
auto $GOPATH 以下のディレクトリにあるパッケージは GOPATH モードで,それ以外はモジュール対応モードで動作する
off 常に GOPATH モードで動作する
on 常にモジュール対応モードで動作する

depからの移行

プロジェクトルートのGopkg.lockファイルを自動に読み込んで、moduleの初期設定を行ってくれる設計になっています。(depから移行するこが前提になっていますね :innocent:
Migrating to Go Modules などが参考になると思います。

  1. 既存のパッケージに go.mod ファイルを追加する
  2. Gopkg.lock ファイルを読んで go.mod ファイルに組み込んでくれる
$ go mod init github.com/my-repo/nice-project
go: creating new go.mod: module github.com/my-repo/nice-project
go: copying requirements from Gopkg.lock

*もちろん、まっさらな状態からgo moduleで初期化と依存パッケージのダウンロードを最初から行ってもいいです。

補足:Dockerでの設定

dockerで開発している場合は、ビルド前に依存パッケージをダウンロード・インストールする必要があります。ポイントだけをピックアップしたDockerfileのイメージです。

# Goのバージョンは1.13以上
FROM golang:1.13-alpine as golang-build

# Goビルドに必要なアプリケーションをインストールする
RUN .....

WORKDIR /go/src/github.com/my-repo/nice-project

# go moduleで依存パッケージを取得してダウンロードする
# ローカルの、go.modとgo.sumをコピー
COPY go.mod go.sum ./
# 依存ライブラリをダウンロードする
RUN go mod download

# Goアプリケーションのビルド
ADD . /go/src/github.com/my-repo/nice-project
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build main.go

ビルド前に、go moduleを使って依存ライブラリ・モジュールをダウンロードしておきます。
とても少ない記述量で実現できてしまいます。

まとめ

depを使っているときはは、CIのビルドの時間を短縮のためにdep ensure -vendor-only=trueとして新しいパッケージを追加する際に、Gopkg.lockとGopkg.tomlを更新していたり手間がかかっていました。modulesでキャッシュディレクトリを設定しておけば、ビルド時間も短縮できるためトリッキーなファイルの運用がなくなりました。1.13がリリースされて4ヶ月位経ちますが、depで苦労していたり、切替をお考えの方がいれば、modulesへの移行の参考になれば幸いです。

76
40
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?