自由拡張
仕様の外を作る
ここまでは、決められた仕様を満たす作業でした。最後は困りごとから機能を考えます。今回の演習ではカテゴリ集計を題材に、並び順を決める部分を作ります。
仕様書に無いものを足すとき、まず考えるのは「誰が何に困っているか」です。
出品者 自分の商品がいくら売れているか知りたい
運営 カテゴリごとの傾向を見たい
購入者 安い順に並べたい困りごとが決まれば、必要なエンドポイントは自然に決まります。
集計 API を足す
このレッスンでは、カテゴリ別の集計を返す API を作ります。
GET /stats
{"stats":[{"category":"本","count":2,"total":2000},{"category":"家電","count":1,"total":24800}]}第5章のマップ、第6章の構造体、第8章の JSON が組み合わさります。これらの処理は補助関数として渡すので、演習では並べ替えの比較に集中できます。
並び順を決める
第5章でやったとおり、マップを回す順番は保証されません。API の応答が毎回違う順で返ると、使う側が困ります。
並び順は使う側の目的に合わせて決めます。演習では比較の条件を指定します。
カテゴリ名の順 安定するが、意味は薄い
件数の多い順 よく使われる。同数のときの決め方が要る
登場順 入力に依存するこの演習では合計金額の多い順にします。同額のときはカテゴリ名の順です。「同じときどうするか」まで決めて初めて、順番が確定します。
並べ替えは sort
Go
import "sort"
// レースの記録をタイムの短い順、同タイムなら名前の順にする例
sort.Slice(runners, func(i, j int) bool {
if runners[i].Seconds != runners[j].Seconds {
return runners[i].Seconds < runners[j].Seconds
}
return runners[i].Name < runners[j].Name
})sort.Slice は、「i が j より前に来るか」を返す関数を渡す形です。true なら i が先です。
> 大きいほうが先(降順)
< 小さいほうが先(昇順)1つ目の条件で差が付かないときだけ、2つ目を見ます。文字列の < は辞書順の比較で、ロケールに応じた五十音順の処理ではありません。
演習の aggregateCategories は件数と合計を数えて構造体スライスへ変換します。登場順の結果を受け取り、比較関数で金額とカテゴリ名の優先順位を決めてください。sort.Slice は元のスライスを並べ替えるため、JSON化する前に呼びます。
並行にするか
第7章でゴルーチンを学びましたが、この規模では使わないほうがよいです。
数十件の集計 ゴルーチンの準備のほうが高くつく
数万件の集計 分割して並行にする価値がある
外部への問い合わせが複数 待ち時間が重なるので効く並行にすれば速くなる、ではありません。待ち時間があるときに効く道具です。使いどころを見極めるのも、覚えたことの一部です。
要件
- 用意済みの集計結果を
sort.Sliceで並べる - 合計金額が違う場合は多いカテゴリを先にする
- 同額の場合はカテゴリ名を文字列の
<で比較し、小さいカテゴリを先にする - 用意済みのJSON応答と空スライスの処理を使う