Start learning free

LESSON 67 OF 173 · BACKEND: APIS WITH A DATABASE

One Product from the Database

Practice

To read one product, a client puts its id in the path: /products/3. A pattern written as "GET /products/{id}" catches that piece of the path. r.PathValue("id") gives it to you as text, and strconv.Atoi turns it into a number.

This time the database does the searching, with a WHERE condition. You never paste the value into the SQL text: you write a placeholder, ?, and pass the value separately, as an extra argument after the SQL. An id matches at most one row, so you ask with db.QueryRow. Its Scan copies that row into your variables, or returns the error sql.ErrNoRows when the query found nothing. For example, with a table books:

var title string
err := db.QueryRow("SELECT title FROM books WHERE year = ?", 1965).Scan(&title)
if err == sql.ErrNoRows {
	fmt.Println("No book from 1965")
}

When no row matches, the client asked for something that doesn't exist, so the answer is 404 with an error message. Writing an answer doesn't end the handler: return right after it, so nothing else is written.

GET /products/3   →  200  {"id": 3, "name": "Lamp", "price": 29, "category": "home", "stock": 1}
GET /products/8   →  200  {"id": 8, "name": "Gift card", "price": 50, "category": null, "stock": 999}
GET /products/99  →  404  {"error": "Product not found"}
GET /products/0   →  404  {"error": "Product not found"}

Your task: add a handler for GET /products/{id} that asks the database for that product with a placeholder and answers it as JSON, or {"error": "Product not found"} with the status 404.


Assignment
Follow the Coding Tutorial to add the handler for GET /products/{id}.


Hint
Scan returns sql.ErrNoRows when the query finds nothing. Check for it, answer 404 and return, before you send p with 200.


STEP 1 OF 9
    Ctrl + Enter to check