問題のコード
func NewCreateAccountInteractor(
repo domain.AccountRepository,
presenter CreateAccountPresenter,
t time.Duration,
) CreateAccountUseCase {
return createAccountInteractor{
repo: repo,
presenter: presenter,
ctxTimeout: t,
}
}
フルのコード
ポイント1:インターフェースとは?
Goのインターフェースは「メソッドの集合」のこと。
つまり、特定のメソッドを持っていれば、その型はインターフェースを実装しているとみなされる。
type CreateAccountUseCase interface {
Execute(context.Context, CreateAccountInput) (CreateAccountOutput, error)
}
CreateAccountUseCase
はExecute
メソッドを持っているものを指す。- 明示的に
implements
とは書かない。
ポイント2:createAccountInteractor
は Execute
を持っている
type createAccountInteractor struct {
repo domain.AccountRepository
presenter CreateAccountPresenter
ctxTimeout time.Duration
}
func (a createAccountInteractor) Execute(ctx context.Context, input CreateAccountInput) (CreateAccountOutput, error) {
// 実装
}
-
createAccountInteractor
にはExecute
メソッドがある。 - だから、Goの型システムが「この構造体は
CreateAccountUseCase
を満たしている」と認識する。
func(a createAccountInteractor)...の文法については以下を参照
ポイント3:NewCreateAccountInteractor
の戻り値
func NewCreateAccountInteractor(
repo domain.AccountRepository,
presenter CreateAccountPresenter,
t time.Duration,
) CreateAccountUseCase {
return createAccountInteractor{ // ここで構造体を返している
repo: repo,
presenter: presenter,
ctxTimeout: t,
}
}
-
CreateAccountUseCase
はExecute
を持つものならOK! -
createAccountInteractor
はExecute
を持っているのでOK! - だから、
createAccountInteractor
を返してもエラーにならない。
わかりやすい例
例1:シンプルなインターフェースと構造体
package main
import "fmt"
// インターフェース
type Speaker interface {
Speak() string
}
// 構造体
type Person struct {
Name string
}
// `Person` は `Speaker` を実装している
func (p Person) Speak() string {
return "Hello, my name is " + p.Name
}
// `Speaker` を返す関数
func NewPerson(name string) Speaker {
return Person{Name: name} // Personを返しているけどOK
}
func main() {
var s Speaker = NewPerson("Alice")
fmt.Println(s.Speak()) // "Hello, my name is Alice"
}
-
NewPerson
はSpeaker
型を返すと言っている。 -
Person
はSpeak
を持っているので、Goの型システムが「これはSpeaker
を満たしている」と判断。 - だから
Person
をSpeaker
として返してもOK!
例2:ポインタを使う場合
func NewPerson(name string) Speaker {
return &Person{Name: name} // ポインタを返す
}
-
&Person{}
にすると、ポインタを返すことになる。 -
Speaker
にポインタが必要な場合はこうする。
結論
createAccountInteractor
は Execute
を持っているから CreateAccountUseCase
を満たす。
だから、CreateAccountUseCase
を返す関数で createAccountInteractor
を返しても問題ない!