paging

paging computes pagination metadata (current page, total pages, previous/next page numbers, and SQL OFFSET/LIMIT values) from three inputs: current page number, page size, and total item count.

Part of nurago, a collection of independent Go packages for backend services.

import "github.com/tecnickcom/nurago/pkg/paging"

Package paging computes pagination metadata (current page, total pages, previous/next page numbers, and SQL OFFSET/LIMIT values) from three inputs: current page number, page size, and total item count.

Usage

New accepts the three caller-supplied values and returns a fully populated Paging struct in a single call. Out-of-range inputs are clamped automatically so callers never need to guard against zero page sizes or page numbers beyond the last page:

p := paging.New(currentPage, pageSize, totalItems)
// p.Offset and p.PageSize are ready for use in a SQL LIMIT/OFFSET clause.
// p.PreviousPage and p.NextPage are safe to embed in a JSON response.

For cases where only SQL values are needed:

offset, limit := paging.ComputeOffsetAndLimit(currentPage, pageSize)

Computed Values

For 17 items displayed 5 per page, navigating to page 3:

p := paging.New(3, 5, 17)
// p.CurrentPage     == 3
// p.PageSize        == 5
// p.TotalItems      == 17
// p.TotalPages      == 4
// p.PreviousPage    == 2
// p.NextPage        == 4
// p.Offset          == 10  (used as SQL OFFSET)
// p.HasPreviousPage == true
// p.HasNextPage     == true

Edge cases

  • Empty result set: with totalItems == 0, New returns TotalPages == 1, CurrentPage == 1 and Offset == 0 (never zero pages and never a panic). Callers detect an empty set via TotalItems == 0, not via the page fields.
  • Offset overflow: if the offset multiplication overflows uint (only reachable through ComputeOffsetAndLimit with a currentPage far beyond the data, since New clamps currentPage to the last page), the offset is clamped to math.MaxUint as a “beyond range” sentinel that selects no rows, rather than wrapping to a wrong offset.
  • JSON numeric precision: fields are plain integers, but JSON numbers are float64 in some clients (e.g. JavaScript), which cannot represent values above 2^53 exactly. Realistic pagination magnitudes stay well below that; the math.MaxUint offset sentinel does not, so treat it as “no rows”.

When To Use

  • A list endpoint returns page metadata alongside results.
  • You need the matching OFFSET and LIMIT for the query.

Example

var (
	currentPage uint = 3
	pageSize    uint = 5
	totalItems  uint = 17
)

// calculate new paging parameters
p := paging.New(currentPage, pageSize, totalItems)

fmt.Println(p)

// Output:
// {3 5 17 4 2 4 10 true true}

Full source is in example_paging_test.go. More runnable examples are on pkg.go.dev.

Dependencies

This package reaches no external module: it uses only the Go standard library.