メインコンテンツにスキップ
モジュール 5 · レッスン 2 / 5コース内の 22/50~14 min
モジュールのレッスン (2/5)

メソッド: 値とポインター レシーバー

Go の メソッド は レシーバー を備えた関数です。つまり、特別な func とメソッド名の間で宣言されたパラメーター。 メソッドを型に変換します。クラスはありません: メソッドは定義できます 現在のパッケージで宣言されている名前付き型。

構文

Go
type Person struct {
    Name string
}

func (p Person) Greet() string {
    return "ciao " + p.Name
}

p := Person{Name: "Ada"}
fmt.Println(p.Greet())   // "ciao Ada"

レシーバー p Person は、Greet を Person のメソッドにします。内部 メソッド p は、他の変数と同様の変数です。

値レシーバーとポインターレシーバー

Go
// VALUE receiver: operates on a COPY of the value
func (p Person) NameUpper() string {
    return strings.ToUpper(p.Name)
}

// POINTER receiver: operates on the original value, can mutate it
func (p *Person) Rename(n string) {
    p.Name = n
}

ポインタ レシーバを使用すると、レシーバを変更し、その変更を行うことができます メソッドの外側から見ることができます。値レシーバーを使用すると、次のことはできません。 ローカルコピーのみを変更してください。

Go
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name)   // "Grace" — change is visible

ポインターレシーバーを使用する場合

実際のルールを優先順位順に示します。

  1. レシーバーを変更する必要があります → ポインタ レシーバー。必須。
  2. 構造体が大きい (数十のフィールド、内部に配列) → ポインタ 高価なコピーを避けるための受信機。
  3. 一貫性: 型の少なくとも 1 つのメソッドにポインター レシーバーがある場合、次を使用します。 他のものに対するポインタ受信機も同様です。にとって非常に重要な大会 インターフェイス (モジュール 6)。
  4. 小さく、不変の、「値」型 (time.Time、複素数、小さい) 構造体) → 値レシーバー、より読みやすくなります。

非構造体型のメソッド

パッケージ内で宣言された任意の NAMED 型に対してメソッドを定義できます。

Go
type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

t := Celsius(20)
fmt.Println(t.ToFahrenheit())  // 68

他のパッケージの型 (int、string など) にそれらを定義することはできません。 まずローカルの名前付き型を作成します。

試してみてください

運動#go.m5.l2.e1
試行回数: 0読み込み中…

「ciao <Name>」を返す Greet() 文字列メソッド (値受信者) を Person に追加します。

エディターを読み込み中…
ヒントを表示

メソッド名の前のかっこ内のレシーバー。

3 回の試行後に解決策が利用可能になります

運動#go.m5.l2.e2
試行回数: 0読み込み中…

p.Name を変更する POINTER レシーバーを備えた Rename(n string) メソッドを追加します。

エディターを読み込み中…
ヒントを表示

ポインタ受信者: `(p *人)`。

3 回の試行後に解決策が利用可能になります

Quiz#go.m5.l2.e3
準備完了

ポインタ レシーバ (p *T) を使用する必要があるのはどのような場合ですか?

Go
func (t ?T) M() { ... }
回答の選択肢

要約

  • メソッド = レシーバーを備えた関数: func (r T) Name(...) ... { ... }。
  • 値レシーバ: コピーに対して動作します。ポインタ受信機: オリジナルで動作します。
  • Go は呼び出しサイトで T ↔ *T 変換を自動的に実行します。
  • ポインター レシーバーの場合: 突然変異 + 大きな構造体 + この型の他のメソッドとの一貫性。
  • 同じ型で値レシーバーとポインター レシーバーを決して混在させないでください。
  • メソッドは、現在のパッケージ (非構造体を含む) 内の NAMED 型に適用されます。