Packages

paginate

Offset pagination parameters with sane defaults and hard limits. Binds straight from the query string, clamps hostile input, and computes the SQL OFFSET for you.


In the handler

import "github.com/BounkhongDev/bkgo/paginate"

// In your handler — bind the query string, then clamp it
var p paginate.Params
c.QueryParser(&p)
p.Normalize()          // ?page=0&limit=999 → page=1, limit=20

users, total, err := h.usecase.List(c.Context(), p)
return c.JSON(response.Paginated(users, p.Page, p.Limit, total))

In the repository

// In your repository — Offset() computes the SQL OFFSET
func (r *repository) List(
    ctx context.Context, p paginate.Params,
) ([]User, int, error) {
    var users []User
    var total int64

    r.db.Session(ctx).Model(&User{}).Count(&total)
    err := r.db.Session(ctx).
        Limit(p.Limit).
        Offset(p.Offset()).
        Find(&users).Error

    return users, int(total), err
}

What Normalize() clamps

Call Normalize() once, right after binding the query string. It rewrites the params in place — anything out of range falls back to the default rather than erroring:

QueryAfter Normalize()
?page=0page = 1
?page=-5page = 1
?limit=0limit = 20
?limit=999limit = 20
?limit=50limit = 50

API

const (
    DefaultPage  = 1
    DefaultLimit = 20
    MaxLimit     = 100
)

type Params struct {
    Page  int `json:"page"  query:"page"`
    Limit int `json:"limit" query:"limit"`
}

// Normalize clamps Page and Limit to valid ranges in-place.
func (p *Params) Normalize()

// Offset returns the SQL OFFSET value for the current page.
// It reads Page and Limit without mutating the receiver.
func (p *Params) Offset() int