Start learning free

LESSON 66 OF 173 · BACKEND: APIS WITH A DATABASE

Rows as Dictionaries

Practice

rows.Scan goes by position: the first column goes into the first address you pass, the second into the second. Nothing in it says "price". If someone changes the order of the columns in the SELECT, the values silently land in the wrong fields.

The names come from the struct: each field's tag gives its JSON key, so a new column needs a new field with its tag. The query can ask for every column with SELECT *, in the table's order, and Scan then needs exactly one address per column. For example, with a table books:

type Book struct {
	Title string `json:"title"`
	Year  int    `json:"year"`
	Pages int    `json:"pages"`
}

rows, _ := db.Query("SELECT * FROM books")
defer rows.Close()
for rows.Next() {
	var b Book
	rows.Scan(&b.Title, &b.Year, &b.Pages)
	fmt.Println(b.Title, b.Pages)   // could print: Dune 412
}

With too few addresses, Scan copies nothing and returns an error; if your code ignores that error, every field keeps its zero value. With one address per column, the products' stock comes along too.

GET /           →  200  Welcome to the shop!
GET /products   →  200  [{"id": 1, "name": "Mug", "price": 12, "category": "kitchen", "stock": 10},
                         {"id": 2, "name": "Notebook", "price": 7, "category": "office", "stock": 0},
                         … 8 products in all …
                         {"id": 8, "name": "Gift card", "price": 50, "category": null, "stock": 999}]

Your task: add a Stock field to Product, ask for every column of products with SELECT *, and scan all five columns into each product.


Assignment
Follow the Coding Tutorial to add the stock field, switch the query to SELECT * and scan every column.


Hint
SELECT * gives the columns in the table's order: id, name, price, category, stock. Pass Scan one address for each, in that order, or it fills nothing.


STEP 1 OF 3
    Ctrl + Enter to check