Gorm is a fantastic ORM writen in Go for gophers.
Today I will show you how to create pagination using Gorm Scopes.
Scopes allow you to re-use commonly used logic, the shared logic needs to be defined as type
func(*gorm.DB) *gorm.DB
The first step is create a Pagination struct.
//pkg.pagination
package pkg
type Pagination struct {
Limit int `json:"limit,omitempty;query:limit"`
Page int `json:"page,omitempty;query:page"`
Sort string `json:"sort,omitempty;query:sort"`
TotalRows int64 `json:"total_rows"`
TotalPages int `json:"total_pages"`
Rows interface{} `json:"rows"`
}
func (p *Pagination) GetOffset() int {
return (p.GetPage() - 1) * p.GetLimit()
}
func (p *Pagination) GetLimit() int {
if p.Limit == 0 {
p.Limit = 10
}
return p.Limit
}
func (p *Pagination) GetPage() int {
if p.Page == 0 {
p.Page = 1
}
return p.Page
}
func (p *Pagination) GetSort() string {
if p.Sort == "" {
p.Sort = "Id desc"
}
return p.Sort
}
Second step is create a Gorm Scope.
func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) func(db *gorm.DB) *gorm.DB {
var totalRows int64
db.Model(value).Count(&totalRows)
pagination.TotalRows = totalRows
totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.Limit)))
pagination.TotalPages = totalPages
return func(db *gorm.DB) *gorm.DB {
return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())
}
}
The third step is use Gorm scope in your repository.
type CategoryGorm struct {
db *gorm.DB
}
func (cg *CategoryGorm) List(pagination pkg.Pagination) (*pkg.Pagination, error) {
var categories []*Category
cg.db.Scopes(paginate(categories,&pagination, cg.db)).Find(&categories)
pagination.Rows = categories
return &pagination, nil
}
Rest Example
I won't talk about how you could implement your handles or access the repository, maybe another time.
The most important thing you need is to return the pkg.pagination for you client.
In a rest application, if I send
http://localhost:3000/categories?limit=10&page=5
Then the output would be:
{
"limit": 10,
"page": 5,
"sort": "Id desc",
"total_rows": 41,
"total_pages": 5,
"rows": [
{
"id": "0acd5600-51b9-42e9-9fd0-ff422a6de1d1",
"category": "example41"
}
]
}
Top comments (4)
Thank you this is good
for those using gin , you can dynamically pick the parameters like this
Thanks. Was helpful
If you use this on a rest API per the post, be sure to validate the sort string against a whitelist of approved fields.
Otherwise you get SQL injection right here:
return db.Offset(pagination.GetOffset()).Limit(pagination.GetLimit()).Order(pagination.GetSort())
gorm.io/docs/security.html#SQL-inj...
great article!