Goのインターフェースの話
インターフェースを返すコードが間違っているという記事を見た。
私も大体同じような実装をしていた。もともとは誰かが公開していたソースコードを真似して書いていたと思う。
違ったのは「おまじない」の部分を書いていないことだけだ。
しかしmattnさんのツイートによると、上記記事が参照しているのは決して全Goユーザーへ向けたレビューポイントではないらしい。
そのためインターフェースを返す実装は間違っているわけではない。以上。
ただ私の実装は「何のためにインターフェースを書いているのかな……」と思うことがあって、どちらかというと使う側でインターフェースを定義するほうがしっくり来たので、インターフェースは使う側で定義するように修正してみた。
今までの実装
package producer
import "database/sql"
type IProducerRepository interface {
Count() (int, error)
}
type ProducerRepository struct {
*sql.DB
}
func NewProducerRepository(db *sql.DB) IProducerRepository {
return &ProducerRepository{db}
}
package consumer
import "gitlab.com/k1350/sololog_gql/internal/repository/producer"
type ConsumerUsecase struct {
producerRepository producer.IProducerRepository
}
func NewConsumerUsecase(ur producer.IProducerRepository) *ConsumerUsecase {
return &ConsumerUsecase{producerRepository: ur}
}
インターフェースは使う側で定義する実装
package producer
import "database/sql"
type ProducerRepository struct {
*sql.DB
}
// 戻り値はインターフェースではない
func NewProducerRepository(db *sql.DB) *ProducerRepository {
return &ProducerRepository{db}
}
package consumer
// インターフェースは使う側で定義する
type IProducerRepository interface {
Count() (int, error)
}
type ConsumerUsecase struct {
producerRepository IProducerRepository
}
func NewConsumerUsecase(ur IProducerRepository) *ConsumerUsecase {
return &ConsumerUsecase{producerRepository: ur}
}
なお『オレの書くGoは間違っていた』の記事だとDIツールを使っているのだが、別に使わなくても *ProducerRepository
は IProducerRepository
を引数として受け入れる関数に渡せるので、元筆者の方がどういう意図でDIツールを使っていたのかはわからなかった。
以上