Goの構造体のフィールドに関数を埋め込んでDIを実現してみる

## 構造体に関数を埋め込むとは

以下のように構造体にメソッドを生やすことが多いと思う。

```go
package main

import (
    "fmt"
)

type Hoge struct {
}

func (h *Hoge) Foo(bar string) string {
    return fmt.Sprintf("%sだ!", bar)
}

func main() {
    h := &Hoge{}

    fmt.Println(h.Foo("sekky0905"))
}
```

実行結果

```
sekky0905だ!
```

実は、構造体のフィールドに関数を埋め込むことができる。

[The Go Programming Language Specification - The Go Programming Language](https://golang.org/ref/spec)にも、以下のような例が存在している。

```go

// A struct with 6 fields.
struct {
	x, y int
	u float32
	_ float32  // padding
	A *[]int
	F func()
}
```

引用元 : [The Go Programming Language Specification - The Go Programming Language](https://golang.org/ref/spec#Struct_types)

なので、以下のようなコードを実装することができる。

```go

import "fmt"

type Hoge struct {
    Foo func(bar string) string
}

func main() {
    f := func(bar string) string {
        return fmt.Sprintf("%sだ!", bar)
    }

    h := &Hoge{Foo: f}

    fmt.Println(h.Foo("sekky0905"))
}
```

実行結果

```
sekky0905だ!
```

## 使い所
会社の先輩にこの埋め込みの関数の使い所を聞いたところ、「関数をDIで渡したいときとかに使うと便利だよ」
と教えていただいたので、実際に簡単にサンプルを書いてみた。

### サンプル
Strategyパターンもどきを実装してみた。

Strategyパターンは、以下のようなもの。

> Strategy パターンは、コンピュータープログラミングの領域において、アルゴリズムを実行時に選択することができるデザインパターンである。

引用元 : [Strategy パターン - Wikipedia](https://ja.wikipedia.org/wiki/Strategy_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)

インターフェースと構造体の埋め込みを用いてDIしたパターンと、関数の埋め込みを用いてDIしたパターンを実装してみたい。

#### インターフェースと構造体の埋め込みを用いてDIしたパターン

```go

package main

import (
	"fmt"
)

type Strategy interface {
	ExecuteStrategy()
}

type StrategyA struct {
	Name string
}

func (s *StrategyA) ExecuteStrategy() {
	fmt.Printf("%s実行したぜ~!\n", s.Name)
}

func NewStrategyA(name string) Strategy {
	return &StrategyA{
		Name: name,
	}
}

type StrategyB struct {
	Name string
}

func (s *StrategyB) ExecuteStrategy() {
	fmt.Printf("%s実行したよ~!\n", s.Name)
}

func NewStrategyB(name string) Strategy {
	return &StrategyB{
		Name: name,
	}
}

type Player struct {
	Strategy Strategy // Strategy型にすることで、後で埋め込む際にStrategy型を実装した任意の型を埋め込むことができる
}

func main() {
	sa := NewStrategyA("StrategyA")
	p1 := &Player{
		Strategy: sa,
	}

	p1.Strategy.ExecuteStrategy()

	sb := NewStrategyB("StrategyB")
	p2 := &Player{
		Strategy: sb,
	}

	p2.Strategy.ExecuteStrategy()
}

```

実行結果

```
StrategyA実行したぜ~!
StrategyB実行したよ~!
```

ここでのポイントは、Playerに埋め込ませるStrategyフィールドを具体的なStrategyAやStrategyBではなく、Strategy型で定義したことである。こうすることで、Playerをインスタンス化するときに使用するStrategyを選択する余地が生まれる。
(StrategyのフィールドをStrategyAやStrategyBにしちゃうと、どちらかしか埋め込めない)


#### 関数の埋め込みを用いてDIしたパターン

```go

package main

import (
	"fmt"
)

type Player struct {
	ExecuteStrategy func(name string)
}

func ExecuteStrategyA(name string) {
	fmt.Printf("%s実行したぜ~!\n", name)
}

func ExecuteStrategyB(name string) {
	fmt.Printf("%s実行したよ~!\n", name)
}

func main() {
	p1 := &Player{
		ExecuteStrategy: ExecuteStrategyA,
	}
	p1.ExecuteStrategy("StrategyA")

	p2 := &Player{
		ExecuteStrategy: ExecuteStrategyB,
	}
	p2.ExecuteStrategy("StrategyB")
}

```

結果

```
StrategyA実行したぜ~!
StrategyB実行したよ~!
```

ここでのポイントは、PlayerのExecuteStrategyフィールドの関数のシグネチャを満たしたものであれば、どんな関数でもPlayerに埋め込むことができるということである。

参考 : [Strategy パターン - Wikipedia](https://ja.wikipedia.org/wiki/Strategy_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)

## 参考にさせていただいたURL
[The Go Programming Language Specification - The Go Programming Language](https://golang.org/ref/spec)

[Strategy パターン - Wikipedia](https://ja.wikipedia.org/wiki/Strategy_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)