Menu
Coddy logo textTech

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

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 8/107。

メソッドは、値レシーバまたはポインタレシーバのいずれかを持つことができます。値レシーバは構造体のコピーに対して動作します。ポインタレシーバは元の構造体に対して動作し、そのフィールドを変更することができます。

値レシーバ — コピーに対して動作します

type Counter struct {
    Count int
}

func (c Counter) GetCount() int {
    return c.Count
}

// これはオリジナルを変更しません
func (c Counter) IncrementWrong() {
    c.Count++ // コピーのみを変更します!
}

ポインタレシーバ — オリジナルを変更します

// これはオリジナルを変更します
func (c *Counter) Increment() {
    c.Count++
}

func (c *Counter) Reset() {
    c.Count = 0
}

両方を組み合わせて使用する

func main() {
    counter := Counter{Count: 0}

    counter.Increment()
    counter.Increment()
    fmt.Println(counter.GetCount()) // 出力: 2

    counter.Reset()
    fmt.Println(counter.GetCount()) // 出力: 0
}

メソッドがデータを読み取るだけの場合は、値レシーバを使用します。メソッドが構造体のフィールドを変更する必要がある場合は、ポインタレシーバ (*StructName) を使用します。Goは自動的に参照を処理するため、どちらも同じ方法で呼び出すことができます。

challenge icon

チャレンジ

中級

適切なレシーバ型を使用して、Wallet 構造体にメソッドを追加してください:

  • GetBalance — 値レシーバ、現在の残高を返します
  • Deposit — ポインタレシーバ、残高に金額を加算します
  • Withdraw — ポインタレシーバ、十分な資金がある場合にのみ金額を減算します

チートシート

メソッドは、値レシーバまたはポインタレシーバのいずれかを持つことができます。値レシーバは構造体のコピーに対して動作します。ポインタレシーバは元の構造体に対して動作し、そのフィールドを変更することができます。

値レシーバ — コピーに対して動作します:

type Counter struct {
    Count int
}

func (c Counter) GetCount() int {
    return c.Count
}

ポインタレシーバ — 元の値を変更します:

func (c *Counter) Increment() {
    c.Count++
}

メソッドがデータを読み取るだけの場合は、値レシーバを使用します。メソッドが構造体のフィールドを変更する必要がある場合は、ポインタレシーバ*StructName)を使用します。

自分で試してみよう

package main

import "fmt"

func main() {
    var balance, deposit, withdraw float64
    fmt.Scan(&balance, &deposit, &withdraw)

    w := Wallet{Balance: balance}

    fmt.Printf("Balance: %.2f\n", w.GetBalance())

    w.Deposit(deposit)
    fmt.Printf("After deposit: %.2f\n", w.GetBalance())

    w.Withdraw(withdraw)
    fmt.Printf("After withdrawal: %.2f\n", w.GetBalance())

    fmt.Printf("Final balance: %.2f\n", w.GetBalance())
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン