Goでの「MyStruct does not implement MyInterface」エラーの修正方法

intermediate🔷 Go2026-04-19| Go 1.11+ (全バージョン), 全てのOS (macOS, Linux, Windows)

Error Message

cannot use val (type *MyStruct) as type MyInterface in argument to Foo: *MyStruct does not implement MyInterface (missing Method method)
#go#golang#interface#デバッグ#ポインタ

エラーメッセージ

Goを書き始めて1週間も経てば、イライラさせるコンパイラエラーに遭遇したことがあるでしょう。通常、構造体を関数に渡そうとしたときに発生し、コンパイラは次のようなメッセージを表示して処理を停止させます。

cannot use val (type *MyStruct) as type MyInterface in argument to Foo: *MyStruct does not implement MyInterface (missing Method method)

メソッドが存在すると言っているのに、「レシーバ」が間違っているために、さらに混乱を招くエラーが出ることもあります。

cannot use MyStruct{...} (type MyStruct) as type MyInterface in argument to Foo: MyStruct does not implement MyInterface (Method method has pointer receiver)

何が原因なのか?

Goの型システムは明示的であることで有名です。推論しようとする一部の言語とは異なり、Goは構造体のメソッドとインターフェースの定義が完全に一致することを要求します。このエラーは通常、次の3つの特定の問題のいずれかに起因します。

  • ポインタレシーバの罠: メソッドを *MyStruct(ポインタ)に対して定義しているのに、MyStruct(値)を渡している。
  • シグネチャの不一致: 引数や戻り値の型にタイポがある可能性があります。例えば、インターフェースが int64 を要求しているのに int を使用している場合などです。
  • 可視性の問題: インターフェースがエクスポートされた(大文字で始まる)メソッドを期待しているのに対し、メソッドがエクスポートされていない(小文字で始まる)場合。

ステップバイステップの修正方法

1. ポインタレシーバの不一致を解決する

これは9割方の原因です。Goでは、値型のメソッドセットには、ポインタレシーバで定義されたメソッドは含まれません。これにより、元のデータではなくデータのコピーを誤って変更してしまうメソッドの呼び出しを防いでいます。

type MyInterface interface {
    Update(name string)
}

type MyStruct struct {
    Name string
}

// このメソッドは MyStruct ではなく *MyStruct に属します
func (s *MyStruct) Update(name string) {
    s.Name = name
}

リテラルの MyStruct{} を渡そうとすると、コンパイルに失敗します。修正は簡単で、アドレス演算子(&)を使用して代わりにポインタを渡します。

val := MyStruct{}
// Foo(&val) は動作します! Foo(val) は失敗します。

2. シグネチャを完全に一致させる

Goはインターフェースにおける共変戻り値型や自動型キャストをサポートしていません。インターフェースが error の戻り値を期待している場合、メソッドのシグネチャで明示的に error を返すと宣言していない限り、直接 nil を返すことはできません。

誤り:

type Closer interface {
    Close() error
}

// 戻り値の型 'error' が欠落しているため、これは失敗します
func (s *MyStruct) Close() {
    fmt.Println("終了中...")
}

正しい例: シグネチャのすべての文字がインターフェースの定義と一致していることを確認してください。

func (s *MyStruct) Close() error {
    return nil
}

3. パッケージのプライバシーを確認する

他のパッケージで定義されたインターフェースは、エクスポートされたメソッドしか「見る」ことができません。io.Writer を実装しようとしている場合、メソッド名は write ではなく Write である必要があります。小文字のメソッドはパッケージ内でプライベートであり、他の場所で定義されたインターフェースからは見えません。

修正を確認する「プロ」の方法

構造体がインターフェースを満たしているかどうかを確認するために、プロジェクト全体のビルドを待つ必要はありません。Goの開発者は、これらのエラーを即座にキャッチするために「静的インターフェースチェック」を使用します。構造体の定義のすぐ下に次の行を配置してください。

var _ MyInterface = (*MyStruct)(nil)

この行はメモリを割り当てません。単にコンパイラに「*MyStruct へのポインタが MyInterface に代入可能であることを確認せよ」と伝えます。後で実装を壊してしまった場合、IDEでこの行が即座にエラーとしてハイライトされます。

インターフェースのベストプラクティス

  • 一貫性を持たせる: 構造体の一つのメソッドにポインタレシーバが必要な場合は、その構造体のすべてのメソッドでポインタレシーバを使用するようにしてください。これにより、メソッドセットの予測可能性が保たれます。
  • インターフェースを小さく保つ: Goの格言「インターフェースが大きくなるほど、抽象化は弱くなる」に従いましょう。1つのインターフェースにつき1〜3個のメソッドを目指します。
  • ツールを活用する: VS Code や GoLand を使用している場合は、構造体を右クリックして「Implement Interface(インターフェースを実装)」を選択します。これにより正しいシグネチャが自動生成され、タイポを防ぐことができます。

Related Error Notes