This is a helper library which perfectly matches for server-side implementation of @gemcook/pagination
go get -u github.com/gemcook/pagination-goIf you use dep
dep ensure -add github.com/gemcook/pagination-goYour fetching object must implement fetcher interface.
type PageFetcher interface {
Count(cond interface{}) (int, error)
FetchPage(cond interface{}, input *PageFetchInput, result *PageFetchResult) error
}
type PageFetchInput struct {
Limit int
Offset int
Orders []*Order
}Package pagination provides ParseQuery and ParseMap functions that parses Query Parameters from request URL.
Those query parameters below will be parsed.
| query parameter | Mapped field | required | expected value | default value |
|---|---|---|---|---|
limit |
Limit |
no | positive integer | 10 |
page |
Page |
no | positive integer (1~) | 1 |
pagination |
Enabled |
no | boolean | true |
// RequestURI: https://example.com/fruits?limit=10&page=1&price_range=100,300&sort=+price&pagination=true
p := pagination.ParseQuery(r.URL.RequestURI())
fmt.Println("limit =", p.Limit)
fmt.Println("page =", p.Page)
fmt.Println("pagination =", p.Enabled)import "github.com/aws/aws-lambda-go/events"
func Handler(event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// event.QueryStringParameters
// map[string]string{"limit": "10", "page": "1", "pagination": "false"}
p := pagination.ParseMap(event.QueryStringParameters)
fmt.Println("limit =", p.Limit)
fmt.Println("page =", p.Page)
fmt.Println("pagination =", p.Enabled)
}Tell pagination the condition to filter resources.
Then use cond interface{} in Count and FetchPage function.
Use type assertion for cond to restore your fetching condition object.
Optionally, pagination takes orders.
Use pagination.ParseQuery or pagination.ParseMap to parse sort parameter in query string.
Then, just pass Query.Sort to Setting.Orders.
Those query parameters below will be parsed.
| query parameter | Mapped field | required | expected value | default value |
|---|---|---|---|---|
sort |
Sort |
no | +column_name for ascending sort. -column_name for descending sort. |
nil |
import (
"http/net"
"encoding/json"
"strconv"
"github.com/gemcook/pagination-go"
)
type fruitFetcher struct{}
type FruitCondition struct{
PriceLowerLimit int
PriceHigherLimit int
}
func ParseFruitCondition(uri string) *FruitCondition {
// parse uri and initialize struct
}
func handler(w http.ResponseWriter, r *http.Request) {
// RequestURI: https://example.com/fruits?limit=10&page=1&price_range=100,300&sort=+price
p := pagination.ParseQuery(r.URL.RequestURI())
cond := parseFruitCondition(r.URL.RequestURI())
fetcher := newFruitFetcher()
totalCount, totalPages, res, err := pagination.Fetch(fetcher, &pagination.Setting{
Limit: p.Limit,
Page: p.Page,
Cond: cond,
Orders: p.Sort,
})
if err != nil {
w.Header().Set("Content-Type", "text/html; charset=utf8")
w.WriteHeader(400)
fmt.Fprintf(w, "something wrong: %v", err)
return
}
w.Header().Set("X-Total-Count", strconv.Itoa(totalCount))
w.Header().Set("X-Total-Pages", strconv.Itoa(totalPages))
w.Header().Set("Access-Control-Expose-Headers", "X-Total-Count,X-Total-Pages")
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(200)
resJSON, _ := json.Marshal(res)
w.Write(resJSON)
}For full source code, see example/server.go.
Run example.
cd example
go run server.goThen open http://localhost:8080/fruits?limit=2&page=1&price_range=100,300&sort=+price