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

AboutMulti-DriverSQL Files
Select OverviewListGetValueMaps
DBQueryingSelect

Maps

Use db.Maps to read database rows as dynamic map values.

Maps

Use db.Maps when a query returns rows that should be handled as dynamic map[string]any values.

This is useful when the result shape is not stable enough for a struct, or when you want to inspect raw row data.

rows, err := db.Maps(ctx, conn, selectEventsQuery, 10)
if err != nil {
	return nil, err
}

Function

func Maps(ctx context.Context, c db.Conn, query string, args ...any) ([]map[string]any, error)

Maps accepts:

  • a context.Context
  • a db.Conn
  • a SQL or CQL query string
  • optional query arguments

It returns:

[]map[string]any, error

Each map represents one database row.

When to Use Maps

Use db.Maps when:

  • the result shape is dynamic
  • you do not want to define a struct for the query
  • you are building reports or exports
  • you are working with admin tooling
  • you want to inspect raw database values
  • the selected columns may change depending on the query

For stable application models, prefer db.List or db.Get.

Query

For MySQL and Scylla, use ? placeholders.

const selectEventsQuery = `
	SELECT *
	FROM events
	ORDER BY created_at DESC
	LIMIT ?
`

For PostgreSQL, use numbered placeholders.

const selectEventsQuery = `
	SELECT *
	FROM events
	ORDER BY created_at DESC
	LIMIT $1
`

Complete Query Example

This example returns event rows as dynamic maps.

package main

import (
	"context"

	"github.com/netlifeguru/db"
)

const selectEventsQuery = `
	SELECT *
	FROM events
	ORDER BY created_at DESC
	LIMIT ?
`

func ListEvents(ctx context.Context, conn db.Conn, limit int) ([]map[string]any, error) {
	return db.Maps(ctx, conn, selectEventsQuery, limit)
}

Complete Usage Example

This example connects to the database, loads events, and prints map values.

package main

import (
	"context"
	"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")
	}

	conn, err := connectDB()
	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

	events, err := ListEvents(ctx, conn, 10)
	if err != nil {
		log.Fatal(err)
	}

	for _, event := range events {
		fmt.Printf(
			"ID: %v | Type: %v | Payload: %v | Created: %v\n",
			event["id"],
			event["type"],
			event["payload"],
			event["created_at"],
		)
	}
}

Returned Row Shape

Each row is represented as a map[string]any.

For the query above, a row may look like this:

map[string]any{
	"id":         int64(1),
	"type":       "user.created",
	"payload":    `{"name":"John Doe"}`,
	"created_at": time.Now(),
}

The exact Go types depend on the database driver and returned column types.

SQL Aliases

Map keys are based on the returned column names.

Use aliases when selecting computed values or joining tables.

SELECT
	u.id AS user_id,
	u.email AS user_email,
	COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.email

The resulting map will contain the alias names:

map[string]any{
	"user_id":     int64(1),
	"user_email":  "john@example.com",
	"order_count": int64(3),
}

Typed Access

For typed access, convert a result row to mapper.Row.

row := mapper.Row(events[0])

eventType, ok := row.String("type")
if !ok {
	return errors.New("invalid event type")
}

Or use standalone mapper converters:

eventType, ok := mapper.AsString(event["type"])
if !ok {
	return errors.New("invalid event type")
}

Use map values directly when you only need display or generic processing.

Use typed access when values are required for business logic.

Empty Results

If the query returns no rows, db.Maps returns an empty slice.

events, err := db.Maps(ctx, conn, selectEventsQuery, 10)
if err != nil {
	return nil, err
}

fmt.Println(len(events)) // 0

An empty result is not treated as an error.

Driver Placeholder Differences

The Go call stays the same across drivers.

events, err := db.Maps(ctx, conn, selectEventsQuery, 10)

Only the query placeholder syntax changes.

DriverPlaceholder
MySQL?
Postgres$1
Scylla?

Scylla Example

For Scylla, use a query table that matches the lookup pattern.

const selectEventsByTypeQuery = `
	SELECT *
	FROM events_by_type
	WHERE type = ?
	LIMIT ?
`

func ListEventsByType(ctx context.Context, conn db.Conn, eventType string, limit int) ([]map[string]any, error) {
	return db.Maps(ctx, conn, selectEventsByTypeQuery, eventType, limit)
}

Related Helpers

Use db.List when the query returns multiple typed rows.

users, err := db.List[User](ctx, conn, selectUsersQuery, 10)

Use db.Get when the query returns zero or one typed row.

user, found, err := db.Get[User](ctx, conn, selectUserQuery, id)

Use db.Value when the query returns one scalar value.

total, found, err := db.Value[int64](ctx, conn, countUsersQuery)

Related Examples

Standalone examples are available in the examples repository:

  • Select Map

Value

Use db.Value to read a single scalar value from a database query.

Query Objects Overview

Learn how to use db.Query values with ListQuery, GetQuery, ValueQuery, and MapsQuery.

On this page

MapsFunctionWhen to Use MapsQueryComplete Query ExampleComplete Usage ExampleReturned Row ShapeSQL AliasesTyped AccessEmpty ResultsDriver Placeholder DifferencesScylla ExampleRelated HelpersRelated Examples