Go 埋め込み

きっかけ

こちらの記事でクリーンアーキテクチャを勉強していたときに埋め込みについてさらっと使用されていたので自分なりに深堀ってみた。 https://qiita.com/hirotakan/items/698c1f5773a3cca6193e

type UserRepository struct {
    SqlHandler
}

func (repo *UserRepository) Store(u domain.User) (id int, err error) {
    result, err := repo.Execute(
        "INSERT INTO users (first_name, last_name) VALUES (?,?)", u.FirstName, u.LastName,
    )
    if err != nil {
        return
    }
    id64, err := result.LastInsertId()
    if err != nil {
        return
    }
    id = int(id64)
    return
}
type SqlHandler interface {
    Execute(string, ...interface{}) (Result, error)
    Query(string, ...interface{}) (Row, error)
}

UserRepository というstructに構造体にSqlHandler というinterfaceを埋め込んでいる。

UserRepositoryではSqlHandlerのメソッドを使えるようになる。

Goでの埋め込み

参考: https://qiita.com/momotaro98/items/4f6e2facc40a3f37c3c3

interfaceにはstructを埋め込めない

structにはstructを埋め込める interfaceにはinterfaceを埋め込める structにはinterfaceを埋め込める。

埋め込みのメリット

実装を省略できる為 DRY である。

埋め込みの注意点

参考: https://qiita.com/shibukawa/items/16acb36e94cfe3b02aa1 Goの埋め込みで継承はできない。

「名前なしでアクセスできるメンバー変数」というシンタックスシュガーと考えるべきです。

あくまでもDRYの為

埋め込み元と埋め込み先がのメソッドが重複した場合

埋め込み先のメソッドが先に優先される。

あるメソッドは埋め込み元と同じ実装で あるメソッドは独自のメソッドを実装したいときに使用する。

以上。