Start learning free

LESSON 32 OF 173 · BACKEND: YOUR FIRST API

Shop Statistics

Practice

A shop owner likes a quick summary of the shop: how many products it has, the lowest and the highest price, and the average price. None of these numbers is stored. Your route works them out from the products on every request, so they always match the shop.

All four come from a slice of prices. len counts the items, and slices.Min and slices.Max find the smallest and the largest. Go has no built-in sum, so your file gives you a small sum helper that adds up a slice of ints. The average is the sum divided by the count, both turned into float64 so the decimals stay. math.Round rounds to a whole number, so to keep 2 decimal places you round 100 times the average, then divide by 100. The same tools on other numbers:

ages := []int{30, 25, 40}
fmt.Println(len(ages), slices.Min(ages), slices.Max(ages))   // 3 25 40
average := math.Round(float64(sum(ages))*100/float64(len(ages))) / 100
fmt.Println(average)   // 31.67

An empty slice has no smallest number: slices.Min panics on it, and the request gets no answer. So when the shop has no products, answer the count 0 and nil for the other three, in a map[string]any, and stop the handler with return. The JSON encoder sends nil as null, which means "no value". (Go writes a map's keys in alphabetical order.)

Your code must answer these requests, in this order:

GET /stats  →  200  {"average_price": 12.5, "cheapest": 2, "count": 4, "most_expensive": 29}
DELETE /products/1  →  204
GET /stats  →  200  {"average_price": 12.67, "cheapest": 2, "count": 3, "most_expensive": 29}
DELETE /products/2, then /products/3, then /products/4  →  204 each
GET /stats  →  200  {"average_price": null, "cheapest": null, "count": 0, "most_expensive": null}
POST /products  {"name": "Chair", "price": 45, "category": "furniture"}  →  201
GET /stats  →  200  {"average_price": 45, "cheapest": 45, "count": 1, "most_expensive": 45}

Your task: add a route for GET /stats that answers count, cheapest, most_expensive and average_price (rounded to 2 places), with null for the last three when the shop is empty.


Assignment
Follow the Coding Tutorial to build the GET /stats route: collect the prices, handle an empty shop, work out the average, and answer the four keys.


Hint
Check for an empty slice right after the loop, and end that answer with return, before slices.Min and the division. Multiply by 100 before math.Round and divide by 100 after.


STEP 1 OF 9
    Ctrl + Enter to check