1. 正しい商品
  2. 端数は切り捨て
  3. 名前が空
  4. 価格が0
  5. 価格が負の数
コース一覧
Go道場 fleamaをGoで作り直す10問
問7 Itemに魂を込めよ

Go道場 fleamaをGoで作り直す10問

Go入門で身に付けた技を、商店街公式フリマアプリ「fleama」の Goリプレイス計画で試す演習専用コースです。解説はありません。依頼と完成条件だけを読み、白紙から自分で組み立てます。手が止まったときのために、方針・使う構文・部分解の3段階のヒントを各問に用意しています。ゼロ値の予言から始まり、error の受け止め方、for だけのループ、switch と定数、スライスとマップ、構造体とメソッド、ゴルーチンでの並行処理、JSON を返すハンドラを経て、最後は一覧・詳細・出品の3エンドポイントを Node版と互換になるよう組み上げるところまで、10問で Go の主要な道具を一巡します。1問15分から45分、全10問で約5時間です。Go入門を終えて「読めるけれど自分では書けない」と感じている方に向いています。

1
Goリプレイス計画
01. 問1 ゼロ値を予言せよ15分
02. 問2 errを無視するな20分
03. 問3 forしかない世界で集計せよ20分
04. 問4 商品状態で出し分けろ20分
05. 問5 スライスを育てよ25分
06. 問6 マップで在庫台帳25分
07. 問7 Itemに魂を込めよ30分
08. 問8 3本同時に走らせろ35分
09. 問9 JSONで応答せよ35分
10. 問10 総合 リプレイス完遂45分

問7 Itemに魂を込めよ

中段 / 目安 30分

「いよいよ本丸、Item 型の移植です」

凛さんの声が少しだけ弾みました。「構造体、税込価格メソッド、売切れ化メソッド、そして不正な商品を生まれさせない NewItem 関数。TypeScript道場の問4、覚えていますか。あれの Go 版です」

構造体は、値をひとまとめにした型です。

Go

type Item struct { Name string Price int Sold bool }

メソッドは、関数名の前にレシーバを付けて書きます。ここで2種類の書き方が出てきます。

Go

func (i Item) TaxIncluded() int { ... } // 値レシーバ func (i *Item) MarkSold() { ... } // ポインタレシーバ

違いは、元の値を変えられるかどうかです。値レシーバは写しを受け取るので、中で書き換えても呼び出し元には反映されません。元を変えたいならポインタレシーバを使います。売切れ化はまさにそれです。

そしてコンストラクタです。Go に特別な構文はありません。ただの関数です。

Go

func NewItem(name string, price int) (*Item, error) { if name == "" { return nil, errors.New("商品名は必須です") } ... }

作れなかったときに error を返すのが要点です。不正な値を持つ Item を、そもそも存在させない。 検証を入口の1か所に集めておけば、その先では中身を疑わずに済みます。型の門番を、Go 側にも立てます。

完成条件

次の3つを作ってください。

  1. Item 構造体 — Name(string) Price(int) Sold(bool)
  2. TaxIncluded() — 税込価格を返す。消費税は10%で、端数は切り捨て
  3. MarkSold() — Sold を true にする。元の Item が変わること
  4. NewItem(name, price) — 検証つきで (*Item, error) を返す

検証は、名前が空なら 商品名は必須です、価格が 0 以下なら 価格は1円以上です です。

動作を確かめる runItem 関数も書いてください。名前と価格を受け取り、NewItem で作って売切れ化し、結果を返します。作れなかったときは エラー: に続けて理由を返してください。

要件

  1. Item 構造体に Name Price Sold を持たせる
  2. TaxIncluded() は税込価格(10%・切り捨て)を返し、MarkSold() は元の Item の Sold を true にする
  3. NewItem は (*Item, error) を返し、名前が空なら 商品名は必須です、価格が 0 以下なら 価格は1円以上です のエラーにする

入出力例

runItem("レザースニーカー", 4800) → "レザースニーカー 税込5280円 sold=true" runItem("木製のスツール", 3505) → "木製のスツール 税込3855円 sold=true" runItem("", 4800) → "エラー: 商品名は必須です" runItem("レザースニーカー", 0) → "エラー: 価格は1円以上です" runItem("レザースニーカー", -100) → "エラー: 価格は1円以上です"

ヒント

前のヒントを開くと次が開きます。開かずに解けると未開封クリアです

まず `NewItem` の検証を書きます。作れないときは `nil` と `errors.New(...)` を返します

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

関連レッスン

  • 問8 3本同時に走らせろ

    3カテゴリの集計を goroutine で同時に走らせ、チャネルで回収します。

  • 問9 JSONで応答せよ

    構造体タグで Node版と同じフィールド名の JSON を返すハンドラを書きます。

  • 問10 総合 リプレイス完遂

    一覧・詳細・出品の3エンドポイントを、Node版と互換になるよう組み上げます。

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

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

  • メソッドクラスに属する関数
  • 関数処理に名前を付けて再利用できる単位
  • TypeScript静的型を加えた JavaScript の上位互換
  • コンストラクタインスタンス生成時の初期化処理
main.go
学習モード
エディタを読み込んでいます

メモ

問7 Itemに魂を込めよ

⌘S で保存