寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。 投げ銭は kyash_id : chidakiyo マデ

モノレポ(mono repository)内でgoのmoduleを相対パスで利用する方法

f:id:chidakiyo:20190703173656j:plain

goの依存管理ツールはいろいろありますが、最新はGo Modules(mod)を利用することが多くなってきたと思います。 dep(vendor)を利用した依存解決の場合にはgopath配下にあればある程度柔軟に相対的に依存を解決できましたが、 modは普通に利用するとリポジトリにコミットをした状態を期待しているような振る舞いをします。

モノレポで以下のように複数のモジュールを管理している場合には、modでは利用しづらいように思えましたが、 参照しているモジュールをコミットした状態ではなくとも参照したいという要望があったので解決してみました。

project
  ├ a_module
  │  ├ go.mod
  │  └ main.go
  ├ b_module
  │  ├ go.mod
  │  └ hoge
  │     └ say.go
  ...

各モジュールをmod化する

各モジュールをmod化します。 mod init する際に以下のように module 名を設定します。

// a_moduleをmod化
$ cd path/to/project/a_module
$ go mod init a_module

// b_moduleをmod化
$ cd path/to/project/a_module
$ go mod init b_module

作成されたmodファイルは以下のようになります。

a_module/go.mod

module a_module

go 1.12
b_module/go.mod
module b_module

go 1.12

a_moduleからb_moduleを参照する

a_moduleからb_moduleを利用したい場合、a_moduleのmodファイルを以下のように追記します

a_module/go.mod

module a_module

go 1.12

require (
    b_module v0.0.0
)

replace b_module => ../b_module

b_moduleを依存として利用します(require)という記述と、 b_moduleは ../b_module という相対位置にありますという記述が必要になります。 modの相対位置の関係はgo.modファイルがある位置になるようです。

コード側からb_moduleの関数を利用する

先程の記述は依存関係を定義したので、実際にa_moduleのファイルからb_moduleの関数を利用してみます。

a_module/main.go

package main

import (
    "b_module/hoge"
)

func main() {
    hoge.Say() // b_moduleで実装した関数 // Hello
}

main.goが作成できたら go run main.go などで実行します。 実行の際に依存関係の取得が行われます。

ちなみに b_module/hoge/say.go の中身はこんな感じになるかと思います。

package hoge

func Say() string {
    return "Hello"
}

まとめ

このようにmodファイルを構成することでモノレポで管理しているプロジェクトでも 共通のユーティリティモジュールなどを柔軟に参照することができます。

一時 GO111MODULE=off を利用し、vendor(dep) を引き続き利用していましたが、 こちらの方法でも同じように管理できるようになったのでまとめました。

ツッコミどころなどあればコメントください。

次回作の予告

上記のmodでの相対的なモジュール管理はGAEで利用しようとすると、Appengineのbuildのプロセスでは相対的に取得できるはずのモジュールが取得できないため、デプロイがエラーになります。 その部分も回避策があるため次回の記事で書きます。

参考

cmd/go: clarify go.mod documentation for trivial relative modules · Issue #27274 · golang/go · GitHub

go build keeps complaining that: go.mod has post-v0 module path - Stack Overflow