Quick Start
Scan database rows into a typed Go slice.
This guide shows the basic mapper workflow:
- define a Go struct
- query rows from a database
- scan the rows into a typed Go slice
The examples use MySQL through Go’s standard database/sql package, but the same mapping concept applies to any rows compatible with the mapper.Rows interface.
Define a Struct
Create a struct that represents one database row.
Use db tags to match struct fields with database column names.
type User struct {
ID int64 `db:"id"`
Name string `db:"name"`
Email string `db:"email"`
Active bool `db:"active"`
CreatedAt time.Time `db:"created_at"`
}The mapper matches columns by name, not by scan position.
For example, the created_at column is mapped into the CreatedAt field using the db:"created_at" tag.
Query Rows
Query rows using your database driver.
rows, err := db.Query(`
SELECT *
FROM users
ORDER BY created_at DESC
`)
if err != nil {
return nil, err
}
defer rows.Close()The rows value must be compatible with the mapper.Rows interface.
Go’s standard *sql.Rows already provides the required behavior.
Scan Into a Slice
Use ScanStructSlice to load all returned rows into a typed slice.
users, err := mapper.ScanStructSlice[User](rows)
if err != nil {
return nil, err
}The result is a regular Go slice:
for _, user := range users {
fmt.Println(user.Name)
}Complete Query Example
This example defines the model and a small repository-style function.
package main
import (
"database/sql"
"time"
"github.com/netlifeguru/mapper"
)
type User struct {
ID int64 `db:"id"`
Name string `db:"name"`
Email string `db:"email"`
Active bool `db:"active"`
CreatedAt time.Time `db:"created_at"`
}
func getUsers(db *sql.DB) ([]User, error) {
rows, err := db.Query(`
SELECT *
FROM users
ORDER BY created_at DESC
`)
if err != nil {
return nil, err
}
defer rows.Close()
return mapper.ScanStructSlice[User](rows)
}Complete Usage Example
This example connects to the database, loads users, and prints the scanned values.
package main
import (
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
"github.com/joho/godotenv"
)
func main() {
err := godotenv.Load()
if err != nil {
log.Println(".env file not found, I'm using system env variables")
}
db, err := connectDB()
if err != nil {
log.Fatal(err)
}
defer db.Close()
users, err := getUsers(db)
if err != nil {
log.Fatal(err)
}
for _, user := range users {
fmt.Printf(
"ID: %d | Name: %s | Email: %s | Active: %t | Created: %s\n",
user.ID,
user.Name,
user.Email,
user.Active,
user.CreatedAt.Format("2006-01-02 15:04:05"),
)
}
}Next Steps
Use ScanStructSlice for common list queries.
Use ScanStructOne when the query should return exactly one row.
Use ScanStructRows when you want to process rows one by one through a callback.
Use ScanMapRows when the result shape is dynamic and you want map-based rows.
Related Example
A standalone example is available in the examples repository: