0Pricing
Go Academy · レッスン

構造体のメソッド

値レシーバーとポインターレシーバーの違い

「構造体のメソッド」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

メソッドとは

メソッドは、レシーバ引数を持つ関数です。レシーバはfuncキーワードとメソッド名の間に記述され、関数を型に結び付けます。

値レシーバ

値レシーバは構造体のコピーを受け取ります。状態を変更する必要がないメソッドで使用します。

package main
import "fmt"

type Circle struct{ Radius float64 }

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func main() {
    c := Circle{Radius: 5}
    fmt.Printf("%.2f\n", c.Area()) // 78.54
}

ポインタレシーバ

ポインタレシーバを使用すると、メソッドで構造体を変更できます。大きな構造体ではより効率的です。

package main
import "fmt"

type Counter struct{ N int }

func (c *Counter) Increment() { c.N++ }
func (c *Counter) Reset()     { c.N = 0 }

func main() {
    c := Counter{}
    c.Increment(); c.Increment()
    fmt.Println(c.N) // 2
    c.Reset()
    fmt.Println(c.N) // 0
}

ポインタレシーバを使う場合

次の場合はポインタレシーバを使用します。

  • メソッドでレシーバを変更する必要がある場合
  • 構造体が大きい場合(コピーを避けられます)
  • 一貫性を保つ場合。いずれかのメソッドがポインタレシーバなら、すべてのメソッドをそうするべきです

構造体が小さく、メソッドがデータの読み取りだけを行う場合は、値レシーバを使用します。

メソッド式とメソッド値

メソッドは第一級値として使用できます。

package main
import "fmt"

type Adder struct{ Base int }

func (a Adder) Add(n int) int { return a.Base + n }

func main() {
    a := Adder{Base: 10}
    fn := a.Add          // method value — bound to a
    fmt.Println(fn(5))   // 15
}

構造体以外の型のメソッド

構造体に限らず、同じパッケージ内の任意の名前付き型にメソッドを定義できます。

package main
import "fmt"

type Celsius float64

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

func main() {
    t := Celsius(100)
    fmt.Println(t.ToFahrenheit()) // 212
}

ポインタの自動間接参照

メソッドを呼び出すとき、Goは自動的にアドレスの取得や間接参照を行います。手動で(&c).Method()と記述する必要はありません。

package main
import "fmt"

type Box struct{ Val int }

func (b *Box) Double() { b.Val *= 2 }

func main() {
    b := Box{Val: 5}
    b.Double()           // Go auto-takes address
    fmt.Println(b.Val)   // 10
}

メソッドチェーン

レシーバポインタを返すと、メソッドチェーン(ビルダーパターン)を使用できます。

package main
import "fmt"

type Builder struct{ result string }

func (b *Builder) Add(s string) *Builder {
    b.result += s
    return b
}
func (b *Builder) Build() string { return b.result }

func main() {
    s := (&Builder{}).Add("Hello").Add(", ").Add("World").Build()
    fmt.Println(s)
}

Stringメソッド(fmt.Stringer)

String() stringメソッドを実装して、型の出力形式を制御します。

package main
import "fmt"

type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}

func main() {
    p := Point{3, 4}
    fmt.Println(p) // (3, 4)
}

nilポインタのレシーバ

ポインタレシーバを持つメソッドは、nilポインタに対して呼び出すこともできます。デフォルトの動作を実装する場合に便利です。

package main
import "fmt"

type Node struct{ Val int }

func (n *Node) Value() int {
    if n == nil { return 0 }
    return n.Val
}

func main() {
    var n *Node
    fmt.Println(n.Value()) // 0
}

一貫性の原則

Goの標準ライブラリと慣用的なGoコードでは、ある型のすべてのメソッドで同じ種類のレシーバを使用します。つまり、すべてポインタレシーバにするか、すべて値レシーバにします。混在させると、インターフェースで見つけにくいバグの原因になります。

簡単な確認

メソッドで構造体のフィールドを変更できるのは、どのレシーバ型ですか。

まとめ: メソッド

要点:

  • メソッドではfuncとメソッド名の間にレシーバを記述します
  • 値レシーバ: 読み取り専用、小さな構造体向け
  • ポインタレシーバ: 変更、大きな構造体、一貫性の維持に適しています
  • Goは自動的に間接参照するため、(&v).Method()と記述する必要はありません
  • カスタム出力にはString() stringを実装します

練習問題

Balance float64フィールドを持つBankAccount構造体を定義してください。DepositとWithdrawのポインタレシーバメソッド、およびString()の値レシーバメソッドを追加してください。

よくある質問

「構造体のメソッド」レッスンは無料ですか?

はい。「構造体のメソッド」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「構造体のメソッド」で何を学びますか?

値レシーバーとポインターレシーバーの違い ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「構造体のメソッド」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 構造体の定義と利用
  2. 構造体のメソッド
  3. コンストラクターパターン
  4. 匿名構造体とコンポジション
← Go Academyに戻る