ビジネスとIT活用に役立つブログBlog


google/wireを使ってGoでDI(dependency injection)してみる

この記事をシェアする:

今回は、GoでDI(dependency injection)してみたいと思います。

GoでDI用のパッケージはいくつかありますが、今回は「google/wire」を利用します。

GitHub google / wire

フローを把握する

wireを使ってのDIは、以下のフローになります。

  • 「DIしたい対象を生成する関数」を生成する関数を定義する
  • wireコマンドで、上記のファイルから「DIしたい対象を生成する関数」をジェネレートする
  • その関数を利用する

他の言語のDIコンテナと比べると、すこしフローが違うので最初は戸惑うかもしれません。
DIコンテナ(とその設定)を、メタ的に自動生成するイメージに近いかと思います。

チュートリアルで動きを確認する

こちらの公式のチュートリアルを動かしながら動作を確認していきます。

https://github.com/google/wire/blob/master/_tutorial/README.md

まずは、手動でDIするコードで動きを理解しておきます。(予習は大事です)
 main.go を作りその中に以下のコードを書き込みます。

EventはGreeterに依存していて、GreeterはMessageに依存しています。
そして、main関数内でそれぞれの構造体を作り、手動でセットしています。

wireでDIするよう設定する

次に、先程のコードのmain関数を以下にように書き換えます。

 InitializeEvent 関数をコールすると、Eventが返ってくる想定です。
当然ですが、この時点で実行しても InitializeEvent 関数が定義されていないので失敗します。

この InitializeEvent 関数を自動的に作成するのがwireの役割となります。

次に、 wire.go を作り、以下の内容を書き込みます。

 wire.Build に、各構造体を生成する関数(Provider)を渡します。
Providerを渡す順番はどの順番でもよく、wireがシグネチャを解析して適切な順番でコードを生成してくれます。

返り値は、コンパイラの型チェックを満たすために、空の構造体を返します。
この構造体に値を追加してもwireでは無視されるので注意が必要です。

また、このファイルは実ビルド時には必要ないファイルなので、ファイルの最初に Build Constraints を追加して除外しておきます。(空行も必ず入れます)

 Build Constraints については下記を参考にしてください。

https://golang.org/pkg/go/build/#hdr-Build_Constraints

DI用の関数を生成する

では、実際にwireコマンドを実行してDI用の InitializeEvent 関数をジェネレートします。

無事生成されました。

 wire_gen.go を開いてみると、mainパッケージ内にDI用の InitializeEvent 関数が定義されているのが確認できます。

これで、先程のmain関数から利用する準備が整いました。

ビルドして確認する

最後に、実際にビルドして実行してみます。

正常に動作しています。

まとめ

簡単にですが、チュートリアルを動作させて全体的な使い方が理解できたかと思います。

コード量が少ないと手動でDIしてもそれほど苦痛ではありませんが、コード量が増えてくると記述量が増えて辛くなってきます。 wireを導入することで記述量が減りコードを書く負担は下がると思います。
一方、ビルドステップと学習コストは増えます。

どの規模で導入するべきなのかをよく検討する必要があると思います。


この記事のカテゴリ:

SNSで最新の情報を
受け取ることができます!