ポインタレシーバ
CoddyのGOジャーニー「論理とフロー」セクションの一部 — レッスン 8/68。
値レシーバが構造体のコピーを操作するのに対し、ポインタレシーバは元の構造体インスタンスを直接操作します。ポインタレシーバを使用してメソッドを定義すると、そのメソッドはコピーではなく構造体へのポインタを受け取るため、元のデータを変更することができます。
ポインタレシーバを作成するには、レシーバ宣言の型名の前にアスタリスク * を追加します:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // これは元の構造体を変更します
}この例では、(p *Person) はポインタレシーバです。Person インスタンスに対して haveBirthday メソッドを呼び出すと、メソッドは元の構造体へのポインタを受け取ります。このポインタを介して構造体のフィールドに加えられた変更は、元のデータを永続的に変更します。
ポインタレシーバは、メソッドが構造体のフィールドを更新する必要がある場合に不可欠であり、データの状態を変更する操作に最適です。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
チャレンジ
簡単このチャレンジでは、シンプルな銀行口座システムを構築することで、ポインタレシーバを持つメソッドの作成を練習します。Account 構造体を作成し、ポインタレシーバを使用して口座残高を変更できるメソッドを定義します。
3つの入力を受け取ります:
- 口座名義人の名前を表す文字列(例:
"John Smith") - 初期口座残高を表す文字列(例:
"1000.50") - 取引金額を表す文字列(例:
"250.75")
あなたのタスクは以下の通りです:
- 2つのフィールドを持つ
Account構造体を定義します:Name(string) とBalance(float64) - 指定された金額を口座残高に加算する、ポインタレシーバを持つ
depositというメソッドを作成します - 指定された金額を口座残高から減算する、ポインタレシーバを持つ
withdrawというメソッドを作成します - 口座情報を
"Account: [name], Balance: $[balance]"の形式で出力する、値レシーバを持つdisplayBalanceというメソッドを作成します - 入力をパースして
Accountインスタンスを作成します displayBalanceを呼び出して初期残高を表示します- 取引金額を指定して
depositを呼び出します displayBalanceを呼び出して入金後の残高を表示します- 取引金額を指定して
withdrawを呼び出します displayBalanceを呼び出して最終的な残高を表示します
残高は小数点以下2桁の精度で表示する必要があります。このチャレンジは、コピーを操作する値レシーバとは異なり、ポインタレシーバによってメソッドが元の構造体データをどのように変更できるかを示しています。
チートシート
ポインタレシーバは、構造体のコピーではなく構造体へのポインタを受け取ることにより、元の構造体インスタンスを直接操作します。これにより、メソッドが元のデータを変更できるようになります。
ポインタレシーバを作成するには、レシーバ宣言の型名の前にアスタリスク * を追加します:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // これは元の構造体を変更します
}メソッドが構造体のフィールドを更新する必要がある場合は、ポインタレシーバを使用してください。これにより、データの状態を変更する操作に最適になります。
自分で試してみよう
package main
import (
"fmt"
"strconv"
)
// TODO: ここでAccount構造体を定義します
// TODO: ここでポインタレシーバを使用してdepositメソッドを定義します
// TODO: ここでポインタレシーバを使用してwithdrawメソッドを定義します
// TODO: ここで値レシーバを使用してdisplayBalanceメソッドを定義します
func main() {
// 入力を読み込む
var name string
var initialBalanceStr string
var transactionAmountStr string
fmt.Scanln(&name)
fmt.Scanln(&initialBalanceStr)
fmt.Scanln(&transactionAmountStr)
// 文字列の入力を適切な型に変換する
initialBalance, _ := strconv.ParseFloat(initialBalanceStr, 64)
transactionAmount, _ := strconv.ParseFloat(transactionAmountStr, 64)
// TODO: Accountインスタンスを作成します
// TODO: 初回残高の表示、入金の実行、残高の表示、出金の実行、最終残高の表示を行います
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。