問10 総合 リプレイス完遂
師範 / 目安 25分
凛さんが、めずらしく手を止めてこちらを見ました。
「最終ミッションです。fleama API 仕様書のうち、一覧・詳細・出品の3エンドポイント——Node版と完全互換の Go 実装を。互換テストが全部緑になったら、本番を切り替えます」
少し間があって、続けます。
「……fleama の心臓を、あなたに預けます」
ここまでの9問が、そのまま道具になります。今回はそれらを使う検証・経路分岐・検索・採番を完成コードで渡します。あなたは詳細と出品の2か所で、成功と失敗を仕様の応答へ変換します。
| 使うもの | どの問で |
|---|---|
error を受け止める | 問2 |
switch で分ける | 問4 |
| スライスを育てる | 問5 |
| 構造体とコンストラクタ | 問7 |
| 構造体タグと JSON | 問9 |
仕様書(抜粋)
| メソッドとパス | 応答 | ステータス |
|---|---|---|
GET /items | 商品一覧の配列 | 200 |
GET /items/:id | 商品1件 | 200 |
GET /items/:id(無い id・非数値の id) | {"error":"商品が見つかりません"} | 404 |
POST /items | 作られた商品 | 201 |
POST /items(検証で落ちる) | {"error":"<理由>"} | 400 |
JSON のキーは id name price です。エラーの形は {"error":"..."} で統一します。
検証は問7の NewItem に任せてください。名前が空なら 商品名は必須です、価格が 0 以下なら 価格は1円以上です です。両方不正なら名前の検証を先に行います。非数値のIDも詳細の404にします。
補助コードの読み方
findItem は詳細パスからIDを読み、(Item, bool) を返します。見つかれば商品と true、非数値や見つからないIDなら空の構造体と false です。後者では商品をJSONにせず、見つからない理由を返します。NewItem は検証済みで、成功なら商品のポインタと nil、失敗なら nil とエラーを返します。
たとえば別の題材の会員番号検索でも、結果の値より先に成否を見ます。次は findMember が会員と真偽値を返すとした場合の、呼び出し側の抜粋です。
Go
member, found := findMember(number)
if !found {
return "会員がいません"
}
return member.Nameこの ! は真偽値の反転です。商品の応答では、同じように成否を判定してからステータスとJSON本文を組み合わせます。文字列は + でつなぎます。
toJSON は渡した値をJSONの文字列にし、errorJSON は理由を error キーに入れます。書き直す必要はありません。toJSON の引数型 any は異なる型の値を受け取るための型で、ここでは商品・一覧・エラー用マップを受け取ります。中では json.Marshal が返すバイト列を string(b) で文字列にします。渡す型はすべてJSONに変換できるものに限定しています。たとえば toJSON([]string{"北", "南"}) は ["北","南"]、toJSON(12) は 12 という文字列になります。
バイト列の変換も別の題材で確認できます。この例の text は ["北","南"] という文字列です。
Go
encoded, _ := json.Marshal([]string{"北", "南"})
text := string(encoded)経路判定の && は両方の条件が成立することを表します。たとえば enabled && ready は両方が true のときだけ成立します。strings.HasPrefix は先頭が一致するか、strings.TrimPrefix は先頭の指定文字列を取り除く関数です。たとえば strings.HasPrefix("note/8", "note/") は true、strings.TrimPrefix("note/8", "note/") は "8" です。これらの経路処理も用意済みです。
完成条件
handleRequest の詳細と出品の応答だけを完成させてください。メソッド・パス・出品する商品名・価格を受け取り、ステータス|本文 の形で返します。
プレーンテキスト
200|[{"id":1,"name":"レザースニーカー","price":4800}]
404|{"error":"商品が見つかりません"}
201|{"id":3,"name":"木製のスツール","price":3500}
400|{"error":"商品名は必須です"}初期の在庫は id が 1 と 2 の2件です。呼び出すたびにこの初期在庫から始めます。出品したときの id は、いまある最大の id に 1 を足した3です。採番は用意済みの nextID が行います。
未対応のメソッドや知らないパスが来たときは 404|{"error":"見つかりません"} を返してください。
要件
- 一覧の完成コードはそのまま使う。詳細では検索結果の
foundを判定し、成功なら200|とtoJSON(item)、失敗なら404|とerrorJSON("商品が見つかりません")を返す - 出品では生成結果の
errを判定し、エラーなら400|とerrorJSON(err.Error())、成功なら201|とtoJSON(created)を返す - 存在しないIDや非数値IDは詳細の404になる。検証・検索・採番・JSON変換と、未対応のメソッドやパスの404は完成済みの処理を使う
ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです