Querying Rows
Read result sets.
Querying Rows is a free Go Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Querying Result Sets
Use Query for statements that return rows, like SELECT. It returns a *sql.Rows you iterate over. For a single value, QueryRow is simpler.
db.Query
Query sends the SQL and returns rows plus an error. Always check the error before using the rows.
rows, err := db.Query("SELECT id, name FROM users WHERE active = $1", true)
if err != nil {
log.Fatal(err)
}Always defer rows.Close()
The rows hold a database connection until closed. defer rows.Close() returns it to the pool. Forgetting this leaks connections under load.
defer rows.Close()Iterating with rows.Next
rows.Next() advances to the next row and returns false when done. Inside the loop you call Scan to copy column values into variables.
for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}Scan Takes Pointers
Scan writes into the variables you pass, so you must pass pointers (&id, &name). The number and order of pointers must match the selected columns.
Checking rows.Err
The loop can end because data ran out or because an error occurred mid-iteration. After the loop, call rows.Err() to catch any iteration error.
if err := rows.Err(); err != nil {
log.Fatal(err)
}QueryRow for One Row
When you expect exactly one row, QueryRow plus Scan is cleaner. If no row matches, Scan returns sql.ErrNoRows.
var name string
err := db.QueryRow("SELECT name FROM users WHERE id = $1", 7).Scan(&name)
if err == sql.ErrNoRows {
fmt.Println("not found")
}A Runnable Scan Simulation
Real querying needs a database, so this runnable example models the Query, Next, Scan flow over an in-memory slice to show the iteration pattern.
package main
import "fmt"
type Row struct {
ID int
Name string
}
func main() {
rows := []Row{{1, "Ada"}, {2, "Lin"}, {3, "Guido"}}
for i := 0; i < len(rows); i++ {
var id int
var name string
id = rows[i].ID
name = rows[i].Name
fmt.Printf("id=%d name=%s\n", id, name)
}
fmt.Println("scanned", len(rows), "rows")
}Handling NULLs
A NULL column cannot scan into a plain string or int. Use sql.NullString, sql.NullInt64, or a pointer type so the code can tell NULL from an empty value.
var email sql.NullString
rows.Scan(&email)
if email.Valid {
fmt.Println(email.String)
}Scanning Into Structs
The standard library scans into individual variables, not whole structs. You map columns to struct fields by passing &u.ID, &u.Name. Libraries like sqlx automate this.
Avoid SELECT *
List columns explicitly so the Scan order is stable. A schema change that adds a column will silently break a positional Scan if you relied on SELECT *.
Quick Check
Test your querying knowledge.
Recap
You learned querying rows:
- Query returns *sql.Rows; defer rows.Close()
- Loop with rows.Next, copy via Scan into pointers
- Check rows.Err() after the loop
- QueryRow for single rows; sql.ErrNoRows on miss
- Use Null types for nullable columns
Frequently asked questions
Is the “Querying Rows” lesson free?
Yes — the full text of “Querying Rows” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.
What will I learn in “Querying Rows”?
Read result sets. You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Go Academy?
No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Querying Rows” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Go Academy lesson?
Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Opening a Connection
- Querying Rows
- Prepared Statements
- Transactions