go1.11+google/wireによるDependency Injection

# 対象読者
- Javaなどの言語を通してDI自体には触れたことがある（仕組みぐらいは知っている）。
- （公私問わず）Golangの実装経験がある。
- 上記の経験がなくとも、興味がある。

# お題
[DI(Dependency Injection)](https://ja.wikipedia.org/wiki/依存性の注入)という概念はJavaなどの言語ではもう当たり前のように実装されている。
ただ、フレームワークが仕組みを提供することが多いため、実は意識せず使っていることもあるかも。

この仕組みは、Golangでアプリケーションを作成する際にも役に立つはず。
が、Golangにおいては、Java等の言語のようにデファクトスタンダードなDIフレームワークが存在しない（いや、言い切ってはいけない。２年くらいのGolang経験上、知らないだけ）。

そんなとき、Googleが、DIフレームワークとまでは言わないまでも”DIツール”という位置づけで[wire](https://github.com/google/wire)というものを公開していることを知って、試してみようと思った。
（もとは[go cloud](https://github.com/google/go-cloud)というKitに同梱されていたものが切り出されたものであるとのこと。）

今回は、チュートリアルにある内容をそのままトレースするだけ。
なので、「そんなんなら原本を見るからいいよ」という人は下記を参照されたし。
https://github.com/google/wire/blob/master/_tutorial/README.md

# 作業環境
### # OS
```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
```

### # 言語
```
$ go version
go version go1.11.4 linux/amd64
```
# 実践
## wire導入
導入のくだり、及びgo1.11との組み合わせで生じる事象については[前回の記事](https://qiita.com/sky0621/items/105c5c7535a7c8b70489)参照。

## wireチュートリアル
### ■DI対象とする構造
#### 構造体群の定義と依存関係

```go
// --------------------------------------------------------
// [Event]
//     +-- [Greeter]
//             +-- [Message]
// --------------------------------------------------------

// EventはGreeterを持つ
type Event struct {
	Greeter Greeter
}

// GreeterはMessageを持つ
type Greeter struct {
	Grumpy  bool
	Message Message
}

// Message型
type Message string
```

#### 依存関係の生成関数

```go
// Greeterを受け取ってEventを生成する
func NewEvent(g Greeter) (Event, error) {
	if g.Grumpy {
		return Event{}, errors.New("could not create event: event greeter is grumpy")
	}
	return Event{Greeter: g}, nil
}

// Messageを受け取ってGreeterを生成する
func NewGreeter(m Message) Greeter {
	var grumpy bool
	if time.Now().Unix()%2 == 0 {
		grumpy = true
	}
	return Greeter{Message: m, Grumpy: grumpy}
}

// 文字列を受け取ってMessageを生成する
func NewMessage(phrase string) Message {
	return Message(phrase)
}
```

#### 構造体が持つメソッド

```go
// Eventは開始メソッドを持つ
func (e Event) Start() {
	msg := e.Greeter.Greet()
	fmt.Println(msg)
}

// Greeterは挨拶メソッドを持つ
func (g Greeter) Greet() Message {
	if g.Grumpy {
		return Message("Go away!")
	}
	return g.Message
}
```

### ■DI構造を組み立てる関数定義
「wireinject」というビルドタグを付けると、「wire」コマンドによってDIソースが自動生成される。

```go:[wire.go]
//+build wireinject

package main

import "github.com/google/wire"

// 依存する構造体群を生成する関数をすべて渡して、最終的にEventを構築
func InitializeEvent(phrase string) (Event, error) {
	wire.Build(NewEvent, NewGreeter, NewMessage)
	return Event{}, nil
}
```

### ■main関数

```go:[main.go]
func main() {
	e, err := InitializeEvent("hi there!")
	if err != nil {
		fmt.Printf("failed to create event: %s\n", err)
		os.Exit(2)
	}
	e.Start()
}
```

### ■wireコマンドでDI構造組み立てコードを自動生成

上記「wire.go」が存在するパス上でインストール済みの「wire」コマンドを実行すると「wire_gen.go」が自動生成される。

```go:[wire_gen.go]
// Code generated by Wire. DO NOT EDIT.

//go:generate wire
//+build !wireinject

package main

// Injectors from wire.go:

func InitializeEvent(phrase string) (Event, error) {
	message := NewMessage(phrase)
	greeter := NewGreeter(message)
	event, err := NewEvent(greeter)
	if err != nil {
		return Event{}, err
	}
	return event, nil
}
```

### ■実行

```
$ go run main.go wire_gen.go 
hi there!
```

# まとめ
これだけの依存構成では、いまいちありがたみが感じられない。
次の記事では、もう少し実際の業務でありそうな構造で試してみよう。

# 参考
実は既にいろいろ参考になる記事は出ている。
https://qiita.com/po3rin/items/25ffcfc2fa8381b9d591
https://budougumi0617.github.io/2018/12/14/how-to-use-google-wire/
https://blog.ishkawa.org/2018/12/10/1544371624/
https://developers.freee.co.jp/entry/service-infra-and-wire
https://tech.eviry.com/2018/12/27/di-with-wire-golang/
http://midori5.hatenablog.com/entry/2018/07/28/013026