Goのmonorepoで共通処理を利用する方法
はじめに
平下CTO@sweeepです。Go言語でのmicroservicesにおけるmonorepo構成と共通処理を利用する方法を解説します。monorepo構成での共通処理の利用を目的としています。
本記事の内容です。
- monorepoフォルダー構成
- utilsで共通処理
- 各microservice側での利用方法
- 実行結果
monorepoフォルダー構成
monorepo直下にutilsとsrc、src下に各microserviceを配置します。GCP/AWSのデプロイ関連フォルダーもmonorepo直下に置くことが多いと思います。monorepo直下で一括管理し各microserviceのバージョン管理やデプロイの管理がラクになります。
.
└─ utils
| ├── file
| | ├── file.go
| | └─ go.mod
...
└─ src
| ├── aservice
| | ├── main.go
| | └─ go.mod
...
utilsで共通処理の実装
共通処理をutils下にパッケージ名のフォルダー/パッケージ名.goで実装します(以下はfileパッケージのサンプル)。
package file
...
func CheckFileSize(size int64) (int64, error) {
if size > MaxSize { // MaxSizeより大きい場合はエラー
return size, fmt.Errorf("size: %v error: %w", size, ErrFileSize)
}
return size, nil
}
以下のコマンドでパッケージフォルダー下へ移動し、モジュール化実施します。
$ cd /utils/file
$ go mod init
$ go mod tidy
各microservice側での利用方法
以下のコマンドで各microservice下へ移動し、モジュール初期化実施します。service下にmain.go配置が必要です。
$ cd /src/service
$ go mod init
すると、以下のようなgo.modファイルが作成されます。
module github.com/hirac1220/go/go-monorepo/src/service
go 1.17
privateリポジトリのfileパッケージをインポートして利用するために、以下のように相対パスでreplace実施をgo.modに記述します。
replace github.com/hirac1220/go/go-monorepo/utils/file => ../../utils/file
以下のコマンドを実行します。
$ go mod tidy
これでgo.modにfileパッケージを利用するための記述が追加され、準備ができました。
module github.com/hirac1220/go/go-monorepo/src/service
go 1.17
replace github.com/hirac1220/go/go-monorepo/utils/file => ../../utils/file
require github.com/hirac1220/go/go-monorepo/utils/file v0.0.0-00010101000000-000000000000
利用する箇所でfileパッケージをインポートし、file.関数名で利用します。
package main
import (
"log"
"os"
"github.com/hirac1220/go/go-monorepo/utils/file"
)
func main() {
// ファイルサイズチェック
f, _ := os.Open("../../sample/image.jpg") // ファイルオープン
defer func() {
_ = f.Close()
}()
fi, _ := f.Stat()
size, err := file.CheckFileSize(fi.Size()) // ファイルサイズチェック
if err != nil {
log.Println(err)
}
log.Printf("size: %d", size)
}
実行結果
以下コマンドで各microservice下へ移動し、実行するとmain.goからfileパッケージ呼び出して結果が表示されました。
$ cd /src/service
$ go run main.go
2022/02/26 18:30:16 size: 2604
まとめ
今回はGo言語でのmicroservicesにおけるmonorepo構成と共通処理を利用する方法を解説しました。
monorepoを利用することで、各microserviceのバージョン組合せを気にせず管理でき、またデプロイも各microservice毎ではなくmonorepo下を一括デプロイできます。そして、共通処理をutilsへまとめてパッケージ化することで、各microserviceで利用可能となります。
使用したサンプルはこちらのGitHubレポジトリにあります。
Discussion
utilsで共通処理を実装されているとのことですが、 utilsを更新したら各マイクロサービスをデプロイし直す必要があると思います。
切り出し方やデプロイに関して気をつけていることはありますか?
基本的にmonorepoなので一括CICDでビルド&テストを通すのであまり問題はないかと思っています。切り出し方はDRY原則で、同じことをやっている箇所をリファクタして切り出し、または再利用可能性が高いものをあらかじめ切り出す2パターンが多いでしょうか。
ご返信ありがとうございます!それであればバグになってしまうことはなさそうですね。
チームの規模やデプロイの頻度・方法 によって ソースコードDryにするか、完全に独立させるか
議論の余地がありそうですね。
そうですね、そもそもサービスやチーム規模が小さいうちはmicroserviceを採用するかどうか議論した方がよいかな、と思います(最初はMVCとかでさくっと作ってPMF優先など)。コメントありがとうございます!