Go言語学習8日目:メソッドとポインタレシーバ?をゆるっと学んでみた。

Go言語学習も8日目に入りました!
今日は [Go Tour(日本語版)]の「Methods and Interfaces」セクションに取り組んでみました。

go-tour-jp.appspot.com

前回までの取り組みはコチラ

kunio-ud-all.com

このあたりから、少しオブジェクト指向っぽい雰囲気が出てきますが…
ゆっくりコードを動かして理解していくスタイルで進めていきます!


まずはメソッドを定義してみよう

Goでは、構造体に対してクラスのメンバーのようにメソッドを定義できます。

package main

import "fmt"

type Rectangle struct {
    Width  float64
    Height float64
}

// メソッド定義:値レシーバ
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func main() {
    rect := Rectangle{Width: 5, Height: 3}
    fmt.Println("面積:", rect.Area()) // 面積: 15
}
ポイント
  • func (r Rectangle) ← この (r Rectangle) の部分が「メソッドレシーバ」
  • Rectangle 型に Area() という機能を“追加”しているイメージ

インターフェースと似てますよね。なんか、後付けでメソッドが定義できている感じが新鮮。 C#などですと、クラス内に作らないと。というイメージが強く。。 それを打破するために、自分なりにはオブジェクトに後でメソッドを追加する。みたいな感じで認識しようとしています。


ポインタレシーバって何?

Goでは、メソッドのレシーバに「値」か「ポインタ」かを選べます。
以下のような書き方です

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

ポイントは *Rectangle というポインタ型を使っていること。

func main() {
    rect := Rectangle{Width: 2, Height: 4}
    rect.Scale(2) // Width: 4, Height: 8
    fmt.Println("拡大後:", rect)
}
ポインタレシーバを使う理由
  • メソッド内で「構造体の値を書き換えたい」場合に必要
  • 値レシーバ(r Rectangle)だとコピーされるので元の値は変わらない!

値レシーバ vs ポインタレシーバの違い:簡単コードで比較!

package main

import "fmt"

type Counter struct {
    Count int
}

func (c Counter) IncrementByValue() {
    c.Count++
}

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

func main() {
    c := Counter{}

    c.IncrementByValue()
    fmt.Println("値レシーバ:", c.Count) // → 0(変わらない)

    c.IncrementByPointer()
    fmt.Println("ポインタレシーバ:", c.Count) // → 1(反映される!)
}

じゃあ実務ではどっちを使えばいいの?

一般的な指針?
  • 構造体の中身を「変更したい」→ ポインタレシーバ
  • 単に「読み取るだけ」→ 値レシーバ(コピーでもOK)
  • 複数のメソッドがある場合は統一するのが吉(バラバラだと混乱…)

実務ではほとんどがポインタレシーバになるんじゃないかな?


今日のまとめ

Go言語8日目の学習ポイントまとめ
  • メソッドは func (x Type) MethodName() の形で定義できる
  • 構造体に機能を持たせることで、使いやすく整理されたコードに!
  • ポインタレシーバを使えば、構造体の中身を更新できる
  • 値レシーバだとコピーになるため、元のデータは変わらない
  • 「メソッドはオブジェクトっぽく機能を“ひもづける”もの」と捉えると理解しやすい!

文系SE的にも、ここまで来ると 「Goってクラスっぽいこともできるんだな〜」 って気づきが増えてきました。


(以下、広告を含みます)