NetLife Guru

Open source Go packages for fast, maintainable web systems. Built with a documentation-first approach.

Product
OverviewGolang packagesNews
Documentation
DocumentationGo LoggerGo RouterGo DB Form
Company
OverviewContactNewsGitHub
Community / Support
Supportinfo@netlife.guru
© 2026 NetLife Guru. All rights reserved.
GitHubinfo@netlife.guru
NetLife GuruNetLife GuruNetLife Guru
NetLife GuruNetLife GuruNetLife Guru
OverviewDocumentationNewsSupportContact

Golang packages

About
ScanningMaps and RowsConvertersCacheErrors
MappingDynamic RowsEdge Cases
MapperAPI

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

APIPurpose
ScanMapRowsScan database rows into map[string]any values
FillFromMapFill a Go struct from a map[string]any
RowConvenience 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) error

Example:

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 valueStored value
nilnil
[]bytestring
map[string]anyJSON string
[]anyJSON string
other valuesoriginal 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) error

Example:

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:

  1. db tag
  2. json tag
  3. Go field name
  4. 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]any

It 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

MethodReturnsPurpose
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

NeedUse
Process rows dynamicallyScanMapRows
Convert an existing map into a structFillFromMap
Read typed values from a mapRow
Convert individual valuesAsInt, AsString, AsBool, AsTime

Individual converters are documented in the Converters API page.

Scanning

Scan database rows into Go structs using ScanStructRows, ScanStructSlice, and ScanStructOne.

Converters

API reference for converting dynamic row values into common Go types.

On this page

OverviewScanMapRowsQuery ExampleScanned ValuesFillFromMapFillFromMap DestinationRowRow MethodsUsing Row With ScanMapRowsChoosing the Right API