🙆

【Golang】Goでインターフェースを実装する方法3選

2023/08/07に公開

はじめに

Goのインターフェース実装は以下の理由により、少々クセがある。

  • 暗黙的である
  • 実装キーワードが存在しない (implementsとかがない)

そのため、はじめて、Goでインターフェースを実装しようと思ったときは戸惑うことも多くありそうだったので、実装方法を3つ紹介します。

やり方その1: 条件を全て満たす

このやり方が一般的な実装方法になります。
Goでは、インターフェースで定義されているメソッドが全て含まれている場合、暗黙的にインターフェースが実装されていると判断されます。

インターフェース定義

type Human interface {
    Greet() error
}

インターフェース実装

type Samurai struct {}

func (s Samurai) Greet() error {
    fmt.Println("どうも、サムライです。")
    return nil
}
func main() {
    samurai := Samurai{}
    samurai.Greet() // 出力: どうも、サムライです。
}

やり方その2: インターフェースを構造体に埋め込む

埋め込み(embedded)は、構造体とインターフェースに対して使用できます。
埋め込みをすると、Goで継承みたいなことができます。

インターフェース定義

type Human interface {
    Greet() error
}

インターフェース実装

type Samurai struct {
    Human // 埋め込み
}

こうするだけで、インターフェースを実装したと認識してくれます。
上記のコードでは、Greet()を実装していないので、このまま使用すると、存在しないものを実行しようとするのでpanicになってシステムが停止してしまいます。

func main() {
    samurai := Samurai{}
    samurai.Greet() // 実装していないのでエラー
}

やり方その3: インターフェースを満たしている構造体を埋め込む

このやり方は、先程のものと似てますが、実装が完了していないメソッドを実行した際の挙動を変えられるので、個人的に感動しました。

インターフェース定義

type Human interface {
    Greet() error
}

// Humanを満たす構造体を実装する
type UnimplementedHuman struct {}

func (UnimplementedHuman) Greet() error {
    return fmt.Errorf("Not implemented")
}

インターフェース実装

type Samurai struct {
    UnimplementedHuman // Humanを満たしている構造体を埋め込む
}

これでも、インターフェースを実装したと認識してくれます。
上記のコードでも、SamuraiGreet()を実装していませんが、埋め込み元が実装してくれてますので、panicにならず、errを返してくれるので安全に扱うことができます。

func main() {
    samurai := Samurai{}
    samurai.Greet() // 出力: Not implemented
}

Greet()を実装した場合は、ちゃんと実装したものが使用されます。

type Samurai struct {
    UnimplementedHuman
}

func (s Samurai) Greet() error {
    fmt.Println("どうも、サムライです。")
    return nil
}
func main() {
    samurai := Samurai{}
    samurai.Greet() // 出力: どうも、サムライです。
}

おまけ

インターフェース実装を強制したい場合のテクニックをついでに紹介します。
この方法は、埋め込みを使用せずにインターフェースを実装した場合のみ有効なものです。
やり方は超カ簡単で、以下の1行のコードを追加するだけです。

var _ Human = Samurai{} // インターフェースを満たしてないとき、エラーになります。

Discussion