コース一覧
    Go基礎:データ構造
    ポインタレシーバ

    Go基礎:データ構造

    Goのスライス、マップ、構造体、メソッドを使ったデータ表現を学ぶコースです。

    1
    スライスとマップ
    01. 配列15分
    02. スライス15分
    03. appendで育てる15分
    04. rangeで走査する15分
    05. マップ15分
    06. カンマokイディオム15分
    07. つくる: 検索と集計20分
    08. 第5章クイズ10分
    2
    構造体とメソッド
    01. 構造体15分
    02. 初期化とフィールド15分
    03. メソッド15分
    04. ポインタレシーバ20分
    05. New関数の慣習15分
    06. 構造体のスライス15分
    07. つくる: Itemで再設計20分
    08. 第6章クイズ10分

    ポインタレシーバ

    星印を1つ足す

    前のレッスンで、メソッドの中で書き換えても効かない問題がありました。解決策は1文字です。

    Go

    func (i Item) MarkSoldOut()   // 効かない
    func (i *Item) MarkSoldOut()  // 効く

    *Item は「Item そのものではなく、Item の居場所」を表します。

    Go

    func (i *Item) MarkSoldOut() {
    	i.SoldOut = true
    }
    
    item.MarkSoldOut()
    fmt.Println(item.SoldOut)   // true。効いている

    なぜ効くのか

    値レシーバは、呼ぶたびに中身をコピーして渡します。メソッドの中の i は写しなので、書き換えても元には届きません。

    ポインタレシーバは、どこにあるかだけを渡します。メソッドの中の i は元と同じ場所を指しているので、書き換えが元に届きます。

    プレーンテキスト

    値レシーバ      写しを渡す      書き換えても元は無傷
    ポインタレシーバ 場所を渡す      書き換えると元も変わる

    第5章の配列とスライスの違いと、同じ構図です。

    呼び出し側は同じ

    Go

    item.MarkSoldOut()   // どちらでもこう書く

    他の言語なら &item と書く必要がある場面ですが、Go は自動で補います。呼ぶ側からは見分けが付きません。

    楽な反面、メソッドの定義を見ないと書き換わるのかどうか分からない、ということでもあります。

    どちらを使うか

    判断は2つです。

    プレーンテキスト

    中身を書き換える           → ポインタレシーバ
    構造体が大きい(コピーが重い) → ポインタレシーバ
    それ以外                   → 値レシーバ

    もう1つ、実務で効く決まりがあります。1つの型でレシーバを混ぜないことです。

    Go

    func (i Item) Label() string      // 値
    func (i *Item) MarkSoldOut()      // ポインタ

    動きますが、読む人が毎回どちらか確かめることになります。1つでも書き換えるメソッドがあるなら、その型のメソッドは全部ポインタレシーバに揃えるのが慣習です。

    nil に注意

    ポインタは「何も指していない」状態になれます。

    Go

    var i *Item        // nil
    i.MarkSoldOut()    // panic: invalid memory address

    値レシーバでは起こりえない失敗です。ポインタを使う代償として、nil かどうかを気にする場面が増えます。第8章で JSON を読み込むときに、この形が出てきます。

    要件

    1. Sell は在庫を1つ減らす。在庫が0のときは何もしない
    2. 在庫が0になったら SoldOut を true にする
    3. 書き換えが反映されるレシーバを使う
    4. 売切れなら 商品名 売切れ、それ以外は 商品名 在庫N点 を返す

    ヒント

    `func (i *Item) Sell()` のように、レシーバの型に `*` を付けます

    在庫を減らした後に `if i.Stock == 0 { i.SoldOut = true }` を書きます

    在庫より多く売ろうとしても、`if i.Stock > 0` があるのでマイナスにはなりません

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/10

    関連レッスン

    • New関数の慣習

      検証つきの生成関数を書き、不正な商品を作れなくできるようになります。

    • 構造体のスライス

      []Itemで一覧を持ち、全データを構造体前提に移行できるようになります。

    • つくる: Itemで再設計

      第6章の知識で検索と集計をItem対応に書き換え、データ層を構造体に統一できます。

    • 第6章クイズ

      構造体、メソッド、ポインタレシーバ、New関数についての理解を確認します。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • メソッドクラスに属する関数
    • 配列サイズ固定の同型データの集まり
    • スライス範囲指定で部分列を取り出す記法
    • 判断YES/NO 分岐を表す菱形
    • applicationJSON 本文を送るときの Content-Type
    main.go
    エディタを読み込んでいます

    メモ

    ポインタレシーバ

    ⌘S で保存