Golang代码复用-分页最佳实践

分页是查询的一个基本要求之一。这部分代码大多重复,适合复用。下面是一种最佳实践:

这是一个传有分页数据的Gin Handler,它需要对数据库进行分页查询:

1
2
func (p propertyRepository) GetPagedAndFiltered (limit, page int){
}

随后我们定义一个gorm中间件去对数据库进行分页:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import "gorm.io/gorm"  

type paginate struct {
limit int
page int
}

func newPaginate(limit int, page int) *paginate {
return &paginate{limit: limit,page: page}
}

func (p *paginate) paginatedResult(db *gorm.DB) *gorm.DB {
offset := (p.page - 1) * p.limit

return db.Offset(offset).
Limit(p.limit)
}

随后,就可以在数据库中使用分页了:

1
2
3
4
5
6
7
func (p propertyRepository) GetPagedAndFiltered(limit, page int) ([]Property, error) {  
var properties []Property

err := p.db.Scopes(newPaginate(limit,page).paginatedResult).Find(&properties).Error

return properties, err
}

当然,我对上面的代码进行了进一步的集成。虽然损失了低耦合性质,但是只是在Gin使用的话体验拉满:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type Pagination struct {
PageSize int
PageNum int
}

// GetPagination Get pagination info
func GetPagination(c *gin.Context) Pagination {
var data Pagination
pageSize, _ := strconv.Atoi(c.Query("pagesize"))
pageNum, _ := strconv.Atoi(c.Query("pagenum"))
switch {
case pageSize >= 100:
data.PageSize = 100
case pageSize <= 0:
data.PageSize = 10
}
if pageNum <= 0 {
data.PageNum = 1
}
return data
}

func (p *Pagination) PaginatedResults(db *gorm.DB) *gorm.DB {
offset := (p.PageNum - 1) * p.PageSize
return db.Offset(offset).Limit(p.PageSize)
}

使用方法就是在Gin Handler中用GetPagination获取分页参数,然后在model的具体数据库实现操作中使用db.Scopes(page.PaginatedResult).xxx直接分页。

应该是一种最佳实践。

作者

xeonds

发布于

2023-10-07

更新于

2024-06-15

许可协议

评论