今川館

都内勤務の地味OLです

GoのBuild Constraints

go buildでモックモードの成果物をビルドできる(?)

ことの始まりは以下のスライドでデータ取得処理をモックと本物とで入れ替える話を読んだことなのだが、

https://speakerdeck.com/azihsoyn/implementing-go-go-go

スライドにはご丁寧にサンプルコードがリンクしてあって、

https://github.com/azihsoyn/IDDD_go_sample

mock mode

Requires

nothing

$ go build +build=mock
$ ./IDDD_go_sample


説明書きを読むと、 "+build=mock" ってオプションを付けると、モックのデータで稼働させられますよ、ということらしい。

この、"+build=mock" という、いかにも思わせぶりな記述をすると、どういう仕組みでデータ取得処理がモック/本物と切り替わるのかわからなかったので調べた。

謎の記述は「Build Constraints」という仕組み

まことに情けないことに、結局 "+build=チョメチョメ" と指定してもわたしの手元では期待通り動かなかったのだが、どうも "-tags チョメチョメ" と指定すると同じ動きになることは理解した。

Goはビルドのときにビルド対象のソースコードをある程度コントロールできて、そういう仕組みを「Build Constraints」と呼ぶらしい。

build - The Go Programming Language

で、さきほどのサンプルコードをよく見ていくと、

// +build mock

// +build !mock

このような記述がデータ取得処理を担うプログラムの先頭に書いてあった。

https://github.com/azihsoyn/IDDD_go_sample/blob/4f6995a6b9e16e09f20262e19418d8f0e2075eeb/internal/repository/article/article.go#L1
https://github.com/azihsoyn/IDDD_go_sample/blob/4f6995a6b9e16e09f20262e19418d8f0e2075eeb/internal/repository/article/repository.go#L1

例えばPythonDjangoだと、runserverやtestコマンドに "--settings=settings.production" とか "--settings=settings.dev" などとオプションを指定して設定を切り替えて稼働させるが、Goはコンパイル言語なのでビルド時に同様の解決が可能であることを知った。

試してみた

試しに以下の構成でプログラムを書いて試してみると、確かに実行コードの内容を切り替えることができた。

app
├── main.go
└── cfg
     ├── cfg_dev.go
     └── cfg_prod.go

[main.go]

package main

import (
	"./cfg"
	"fmt"
)

func main() {
	fmt.Println(cfg.HELLO)
}


[cfg/cfg_dev.go]

// +build debug

package cfg

const HELLO = "Hello, dev-world."


[cfg/cfg_prd.go]

// +build !debug

package cfg

const HELLO = `*** Danger!! ***
Hello, world.
`

[ビルド/実行結果]

(_go)echizen@Seigaku:~/tokyo/app$ go build
(_go)echizen@Seigaku:~/tokyo/app$ ./app 
*** Danger!! ***
Hello, world.

(_go)echizen@Seigaku:~/tokyo/app$ go build -tags debug
(_go)echizen@Seigaku:~/tokyo/app$ ./app 
Hello, dev-world.

Repositoryパターン

あと、IDDD_go_sampleのサンプルコードでなんでデータの取得処理に「repository」という名前をつけるのか不思議に思ったのだが、これは「Repositoryパターン」というパターンがから来ているらしい。

ASP.NET MVCの開発応用編1 ~リポジトリパターンをマスターする~ (1/5):CodeZine(コードジン)

リポジトリパターンはアプリケーション(Controller)からデータアクセスロジックの部分だけを抜き取ったリポジトリインターフェイスを実装したリポジトリクラスに接続します。こうすることで、アプリケーション側はEDMやDataSetなどのデータプロバイダを意識することなくデータのやり取りを実現できます

参考リンク

"// +build チョメチョメ"の次に空行を入れないとダメなルールらしいので注意。

GoのBuild Constraintsに関するメモ - Qiita
go build -tagsを使ってRelease/Debugを切り替える - flyhigh
build - The Go Programming Language