ポインタレシーバと値レシーバ
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 8/107。
メソッドには、値レシーバーまたはポインタレシーバーのいずれかを指定できます。値レシーバーはstructのコピーに対して動作します。ポインタレシーバーはoriginalのstructに対して動作し、そのフィールドを変更できます。
値レシーバー:コピーに対して動作する
type Counter struct {
Count int
}
func (c Counter) GetCount() int {
return c.Count
}
// これはオリジナルを変更しません
func (c Counter) IncrementWrong() {
c.Count++ // コピーのみを変更します!
}ポインタレシーバ: original を変更する
// これは元のものを変更する
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
}値レシーバーは、methodがonlyデータを読み取る場合に使用します。ポインタレシーバー(*StructName)は、methodがstructのフィールドをmodifyする必要がある場合に使用します。Goは参照を自動的に処理します。両方とも同じ方法で呼び出します。
チャレンジ
中級正しい receiver 型を使用して、Wallet struct にメソッドを追加します。
GetBalance:値 receiver、現在の balance を returnsDeposit:ポインター receiver、balance に amount を加算Withdraw:ポインター receiver、十分な資金がある場合のみ amount を減算
自分で試してみよう
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())
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー自分で練習してみよう: Goオンラインコンパイラ