コース一覧
    Go実践:並行処理とWeb API
    出品API

    Go実践:並行処理とWeb API

    Goの並行処理とWeb API開発を組み合わせ、実践的なサービス構築へ進むコースです。

    1
    ゴルーチンと並行処理のさわり
    01. ゴルーチン15分
    02. チャネル20分
    03. 待ち合わせ20分
    04. 並行の落とし穴20分
    05. つくる: 並行集計20分
    06. 第7章クイズ10分
    2
    Web API(net/http)
    01. サーバーを立てる20分
    02. ハンドラ関数20分
    03. JSONを返す20分
    04. ルーティング20分
    05. 一覧API20分
    06. 詳細APIと40420分
    07. 出品API20分
    08. つくる: API主要部完成25分
    09. 第8章クイズ10分
    3
    総合制作
    01. 仕様互換を仕上げる25分
    02. Node版と差し替える25分
    03. 1バイナリでデプロイ25分
    04. 自由拡張25分
    05. 完成と次のステップ20分

    出品API

    本文を読む

    ここまでは読み取りだけでした。今度は送られてきたデータを受け取ります。

    Go

    func createHandler(w http.ResponseWriter, r *http.Request) {
    	var item Item
    	err := json.NewDecoder(r.Body).Decode(&item)
    	if err != nil {
    		w.WriteHeader(400)
    		return
    	}
    }

    Decode は、届いた JSON を構造体に流し込みます。Marshal の逆向きです。

    &item の & は何か

    Go

    Decode(&item)   // 居場所を渡す
    Decode(item)    // これでは書き込めない

    第6章のポインタレシーバと同じ話です。Decode は item の中身を書き換えるので、コピーではなく居場所を渡す必要があります。

    & を書き忘れると、Go が教えてくれます。

    プレーンテキスト

    json: Unmarshal(non-pointer main.Item)

    知らないキーは無視される

    JSON

    {"name":"きのこ図鑑","price":1200,"unknown":"何か"}

    unknown に対応するフィールドが無くても、エラーにはなりません。黙って捨てられます。

    逆に、送られてこなかったフィールドはゼロ値のままです。

    JSON

    {"name":"きのこ図鑑"}

    Price は 0 になります。第2章のゼロ値がここでも効いてきます。

    「0円で送ってきた」と「price を送ってこなかった」は区別できません。 どちらも 0 です。だから、受け取ったあとに検証が要ります。

    検証してから受け付ける

    第4章と第6章で書いた検証が、そのまま使えます。

    Go

    if err := validate(item); err != nil {
    	w.WriteHeader(400)
    	w.Write([]byte(fmt.Sprintf(`{"error":%q}`, err.Error())))
    	return
    }

    %q は、文字列をダブルクォートで囲んで埋め込みます。JSON の値として書くときに便利です。

    Go

    fmt.Sprintf(`{"error":%q}`, "価格が0以下です")
    // {"error":"価格が0以下です"}

    201 を返す

    作成が成功したときは、200 ではなく 201 を使います。

    プレーンテキスト

    200 OK        取得できた
    201 Created   新しく作った
    400 Bad Request 送られてきた内容がおかしい

    201 は「作った」という意味です。200 でも動きますが、何が起きたのかが応答から読み取れるほうが親切です。

    このあたりの使い分けは、決まりというより慣習です。チームで揃っていることのほうが、個々の選択より大切になります。

    要件

    1. json.NewDecoder(r.Body).Decode(&item) で本文を読む
    2. 読み取りに失敗したら 400 と {"error":"不正なJSONです"}
    3. validate に通し、エラーなら 400 とその理由
    4. 成功したら 201 と受け取った商品の JSON

    ヒント

    `if err := json.NewDecoder(r.Body).Decode(&item); err != nil {` の形で読み取ります。`&` を忘れないでください

    検証は `if err := validate(item); err != nil {` です。エラーの理由は `err.Error()` で取れます

    `fmt.Sprintf("{\"error\":%q}", ...)` の `%q` が、文字列をダブルクォートで囲んで埋め込みます

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

    関連レッスン

    • つくる: API主要部完成

      第8章の知識でエンドポイント一式を実装し、fleama API仕様との突合を通せるようになります。

    • 第8章クイズ

      net/http、ハンドラ、JSON、ルーティング、ステータスコードについての理解を確認します。

    • 仕様互換を仕上げる

      ステータスコードとエラー形式を仕様に揃え、互換のあるAPIとして仕上げられるようになります。

    main.go
    エディタを読み込んでいます

    メモ

    出品API

    ⌘S で保存