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, errorEach 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.emailThe 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)) // 0An 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.
| Driver | Placeholder |
|---|---|
| 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: