Go Modulesとマルチモジュール構成でGo Homeする方法
Go Modulesでマルチモジュールにする方法がわからなくて調べました。発端は単にgo.mod
がある別モジュールのパッケージをインポートしようとしても出来なかったことです。そこで、Go Modulesでマルチモジュールを実現するためのシナリオを説明してみたいと思います。
TL;DR
- Go Modulesは便利なので使っていこう
- Go Modulesでマルチモジュール構成にする場合はgo.modファイルで
replace
ディレクティブを使おう - マルチモジュール構成の採用には慎重になろう
Go Modulesとは
とりあえず、Go Modules is 何?
という方の為に簡単に説明します。ご存知の方はこの節を飛ばしてください。
Go ModulesはGo 1.11から試験的に導入され、Go 1.13からデフォルトで有効になる予定の新しいパッケージ依存関係の管理方法です。使ってみた実感としてはすでに充分実用的なので新規にプロジェクトを作成する場合はGo Modulesを使って作成することをオススメします。Go 1.12でGo Modulesを有効にするためには、GOPATH以外のパスで作業をするか以下で環境変数を設定します。
1 |
|
この記事ではGo 1.12の前提で解説します。
Go Modulesで管理を始める
基本はディレクトリを作成してgo mod init <モジュール名>
で始められます。
1 |
|
go.mod
というファイルが作成されています。これが依存関係を管理するファイルになります。
1 |
|
まずは基本のおはようの挨拶から
早速ですが、基本どおりHello World
から初めて見ます。ただし、依存関係を入れるために go-figureを利用して挨拶をしてみます。ソースコードは以下の通りです。
1 |
|
go build
をすると依存関係があるパッケージがダウンロードされて、ビルドされます。事前にgo get
する必要がないので、これだけでもGo Modulesの良さがわかります。./go-multi-modules
で実行して無事挨拶ができれば成功です。
1 |
|
go.mod
ファイルを見てみるとrequire
の行が追加されて依存関係が追跡されているのが分かります。
1 |
|
また、go.sumというファイルも生成されます。依存関係の管理はgo.modだけでもできますが、go.sum
は検査用に必要なようです。詳しくは ここを参照してください。
1 |
|
おはようの挨拶をパッケージにしてみる
さて、挨拶は毎日するものです。せっかくなので再利用可能なようにパッケージとして分離してみます。pkg
ディレクトリを作成し[^1]、その下にhello-world
ディレクトリを作成して、その下にhello-world.go
ファイルを作成します。ディレクトリ構成は以下の通りです。今回はhelloworld
というパッケージを作成します。
1 |
|
hello-world.go
ファイルの中身は以下の通りです。
1 |
|
main.go
ファイルは以下のように書き換えます。
1 |
|
go build
でビルドして./go-multi-modules
で実行して同じように挨拶ができたら成功です。
[^1]: pkg
ディレクトリはGo Modulesを使う上で必須ではありませんが、ここではGoの標準レイアウトを採用しています。
Go Homeしようとして失敗する
さて、挨拶も済んだのでもう用はありません。帰宅したくなってきたとします。ただし、帰宅時間まで細かく管理されたくないので別モジュールで管理することを考えます。この場合、pkg
ディレクトリ配下にgo-home
ディレクトリを作成して、go-home
ディレクトリに移動してからgo mod init gohome
を実行します。
ディレクトリ構成は以下のようになります。
1 |
|
go-home
配下のgo.mod
は以下のようになります。初期化しただけなのでrequire
はありません。
1 |
|
home.go
は以下のようになります。
1 |
|
main.go
は以下のように書き換えます。
1 |
|
これをトップディレクトリ(go-multi-modules
ディレクトリ)でgo build
でビルドしようとしたところ以下のようなエラーが出てうまくいきませんでした。どうやらモジュールの読み込みに失敗したようです。
1 |
|
replace
のおかげでGo Homeに成功する
解決方法は簡単で親のgo.mod
に以下のreplace
ディレクティブを記述することでした。
replace go-multi-modules/pkg/go-home => ./pkg/go-home
replace
ディレクティブを記述してgo build
をするとビルドが成功します。
以下はgo build
後のgo.mod
です。依存関係(require
)が追加されています。
1 |
|
さて、ビルドできたら./go-multi-modules
で実行してみましょう。一瞬Hello Worldが表示されてその後Go Home!が実行されます。
我々はようやく成し遂げたのです(笑)。
なぜ、マルチモジュール化したかったのか?
さて、ここまででマルチモジュール化の方法が分かったわけですが、問題の発端のなぜ自分がマルチプロジェクトにしたかったのかをまだ説明していませんでした。
理由としてはC言語のライブラリをビルドしてcgoで呼び出すモジュールを書いたのですが、makeでビルドする必要があったのでgitのサブモジュールでローカルに取り込もうとして、必然的にマルチモジュール構成になりました。ただ本家のFAQでは一つのリポジトリに一つのモジュールをススメているので、一般的にはマルチモジュールの採用には慎重になったほうがいいと思われます。
まとめ
本記事ではGo Modulesにおける「マルチモジュール構成」に焦点を当てて、以下についてストーリ仕立てで解説しました。
- Go Modulesを使って依存関係を管理する方法
- パッケージに分割して呼び出す方法
- マルチモジュール構成にする方法
- ただし安易にマルチモジュール構成にしないほうがよい
- Go Home! する方法[^2]
またこの記事を書くために作成したコードは以下に置きました。
この記事がGo Modulesを使ってモジュール管理を始めようという方、マルチモジュールで躓いた方の参考になれば幸いです。
[^2]: Go Homeはネタなので優しくスルーして頂けると幸いです。