Maps and Rows
API reference for scanning rows into maps, filling structs from maps, and using typed row helpers.
This page documents the map-based APIs in mapper.
Use these APIs when you want dynamic row data, manual mapping, or typed access to values stored in map[string]any.
Overview
| API | Purpose |
|---|---|
ScanMapRows | Scan database rows into map[string]any values |
FillFromMap | Fill a Go struct from a map[string]any |
Row | Convenience type with typed accessors for map values |
ScanMapRows
ScanMapRows scans each database row into a map[string]any and passes it to a callback.
func ScanMapRows(rows Rows, each func(row map[string]any) error) errorExample:
err := mapper.ScanMapRows(rows, func(row map[string]any) error {
fmt.Println(row["id"], row["name"])
return nil
})
if err != nil {
return err
}Each map key is the column name returned by the database driver.
map[string]any{
"id": "u_123",
"name": "Alice",
"email": "alice@example.com",
"active": true,
}ScanMapRows calls the callback once for every row.
If the callback returns an error, scanning stops and the same error is returned.
Query Example
rows, err := db.Query(`
SELECT *
FROM users
ORDER BY name ASC
`)
if err != nil {
return err
}
defer rows.Close()
err = mapper.ScanMapRows(rows, func(row map[string]any) error {
fmt.Println(row["name"])
return nil
})
if err != nil {
return err
}Use ScanMapRows when the result shape is dynamic or when you do not want to define a struct for the query.
Scanned Values
ScanMapRows stores scanned values by column name.
Some values are normalized before they are placed into the map:
| Source value | Stored value |
|---|---|
nil | nil |
[]byte | string |
map[string]any | JSON string |
[]any | JSON string |
| other values | original value |
This makes common database values easier to work with in dynamic row maps.
FillFromMap
FillFromMap fills a struct from a map[string]any.
func FillFromMap[T any](dst *T, m map[string]any) errorExample:
type User struct {
ID string `db:"id"`
Name string `db:"name"`
Email string `db:"email"`
Active bool `db:"active"`
}
row := map[string]any{
"id": "u_123",
"name": "Alice",
"email": "alice@example.com",
"active": true,
}
var user User
err := mapper.FillFromMap(&user, row)
if err != nil {
return err
}FillFromMap uses the same field matching rules as struct scanning:
dbtagjsontag- Go field name
- snake_case fallback
Unknown map keys are ignored.
If a value cannot be assigned to the target field, FillFromMap returns an error.
FillFromMap Destination
The destination must be a non-nil pointer.
var user User
err := mapper.FillFromMap(&user, row)
if err != nil {
return err
}Do not pass a value directly:
// Wrong: destination must be a pointer.
err := mapper.FillFromMap(user, row)Do not pass a nil pointer:
var user *User
// Wrong: destination is nil.
err := mapper.FillFromMap(user, row)Row
Row is a convenience type for working with dynamic row maps.
type Row map[string]anyIt provides typed accessors for common values.
row := mapper.Row{
"id": int64(123),
"name": "Alice",
"active": true,
}
id, ok := row.Int64("id")
if !ok {
return errors.New("invalid id")
}
name, ok := row.String("name")
if !ok {
return errors.New("invalid name")
}
active, ok := row.Bool("active")
if !ok {
return errors.New("invalid active value")
}Row Methods
| Method | Returns | Purpose |
|---|---|---|
Int | (int, bool) | Read a value as int |
Int64 | (int64, bool) | Read a value as int64 |
String | (string, bool) | Read a value as string |
Bool | (bool, bool) | Read a value as bool |
Time | (time.Time, bool) | Read a value as time.Time |
Each method returns the converted value and a boolean.
value, ok := row.String("name")If conversion succeeds, ok is true.
If the key is missing or the value cannot be converted, ok is false.
Using Row With ScanMapRows
You can convert a scanned map into mapper.Row when you want typed accessors.
err := mapper.ScanMapRows(rows, func(m map[string]any) error {
row := mapper.Row(m)
id, ok := row.Int64("id")
if !ok {
return errors.New("invalid id")
}
name, ok := row.String("name")
if !ok {
return errors.New("invalid name")
}
fmt.Println(id, name)
return nil
})Choosing the Right API
| Need | Use |
|---|---|
| Process rows dynamically | ScanMapRows |
| Convert an existing map into a struct | FillFromMap |
| Read typed values from a map | Row |
| Convert individual values | AsInt, AsString, AsBool, AsTime |
Individual converters are documented in the Converters API page.