ProgrammingGo開発者

Goにおける構造体のメソッドはどのように動作しますか?メソッドの宣言と関数の違いは何ですか、そしてエイリアスタイプに対するメソッドの実装はどのようになっていますか?

Hintsage AIアシスタントで面接を突破

回答

Goでは、メソッドはレシーバーを持つ関数であり、どのタイプのメソッドであるかを示します:

type User struct { Name string } func (u *User) SayHello() { fmt.Println("こんにちは、", u.Name) }
  • メソッドは特定の型(例えば、User)に関連付けられていますが、関数はそうではありません。
  • メソッドのレシーバー((u *User))は関数の最初の引数として働きますが、構文と呼び出しは異なります。

重要! メソッドはパッケージ内で定義された型のみに宣言できます(他のパッケージで定義された型、組み込み型を含むにはメソッドは定義できません)。エイリアス(type alias)の動作は特別です:

  • 既存の型に基づいて新しい型を定義する場合(type MyInt int)は、メソッドを追加できます。
  • エイリアスタイプ(type MyInt = int)にはメソッドを追加できません。なぜなら、これは単なるエイリアスだからです。

例:

type MyInt int func (m MyInt) Double() int { return int(m) * 2 } // タイプエイリアス type MyIntAlias = int // func (m MyIntAlias) Double() int { ... } // コンパイルエラー

ひっかけの質問

スライス型 []int またはタイプエイリアスに対してメソッドを宣言できますか?

回答: 組み込み型のスライス([]int)に対してはメソッドを宣言することはできません。新しいユーザー定義型に基づくスライスに対しては、メソッドを追加することができます:

type MySlice []int func (s MySlice) Sum() int { ... } // 許可されている

タイプエイリアスには追加できません:

type SuperSlice = []int // func (s SuperSlice) Sum() int { ... } // エラー

このテーマの微妙な違いを知らないことによる実際のエラーの例


ストーリー

マイクロサービスプロジェクトで、チームはint64のタイプエイリアスを定義し、そのままバリデーションメソッドを宣言しようとしましたが、コードがコンパイルできず、メソッドをサポートするためにすべての構造体をリファクタリングしなければなりませんでした。

ストーリー

バックエンドプロジェクトでカスタムスライスのためのメソッドを書きましたが、偶然にも新しい型(type ... []T)を定義せず、組み込みの[]Tで作業していたため、スライスの要素に対してメソッドを追加できませんでした。

ストーリー

サードパーティパッケージ(例えば、time.Time)の型にメソッドを追加し、日付の操作を標準化しようとしたところ、Goでは不可能であることが判明しました。合成やユーティリティ関数を使用する必要がありました。