Go项目实战—开发完善分页插件(易扩展方式)【goshop开源项目 | 20220424更新】
goshop开源项目的更新
备注:前面项目中用到的代码已经分享到
GitHub/Gitee
中去了,并且以后所有项目中会出现的代码都会提交上去,欢迎查阅。
地址
goshop
感兴趣的可以点个star哦~goshop开源项目的更新
今天在考虑怎么实现数据分页和检索功能:
- 通过传入页数(
page
),分页条数(pageSize
) ,实现数据的limit
分页功能 - 动态支持检索条件和排序的功能
接下来咱们就来实现以上功能
- 首先需要先封装一个
Paginate
的扩展用于对gorm
操作时引用Offset
和Limit
的sql拼合。实现代码过程如下:
package Paginateimport ("github.com/jinzhu/gorm""strconv")// 这里需要注意的是:page和pageSize 的数据类型需要指定// 这里根据我之前封装的:获取全部请求参数的一个map指定的返回类型后,决定使用string类型进行定义func Paginate(page, pageSize string) func(db *gorm.DB) *gorm.DB {return func(db *gorm.DB) *gorm.DB {pageUp, _ := strconv.Atoi(page)if pageUp == 0 {pageUp = 1}pageSizeInt, _ := strconv.Atoi(pageSize)switch {case pageSizeInt <= 0:pageSizeInt = 10}offset := (pageUp - 1) * pageSizeIntreturn db.Offset(offset).Limit(pageSizeInt)}}
- 封装好后,接下来就是使用了,在代码中,分页类我使用在:
model
文件中。相应代码如下:
// 根据检索条件,获取记录行,并获取总记录条数func (Goods) FindAll(DB *gorm.DB, params map[string]interface{}) ([]Goods, int64) {var GoodResult []Goodspage := params["page"].(string) // 对返回的interface类型进行转换成字符串pageSize := params["pageSize"].(string) // 对返回的interface类型进行转换成字符串// 这里使用了过滤,在下面使用Where条件时过滤掉page,pageSizeParamsFilter := utils.ParamsFilter(params, "page,pageSize")// 通过 Scopes 引用加载 分页类中返回的 DB指针DB.Scopes(Paginate.Paginate(page, pageSize)).Where(ParamsFilter).Order("created_at desc").Find(&GoodResult)// 这里时查询全部数据,用于返回总记录条数GoodCount := DB.Find(&Goods{})return GoodResult, GoodCount.RowsAffected}// 这是过滤的封装,一起贴出来了func ParamsFilter(params map[string]interface{}, isFilterStr string) map[string]interface{} {var data = make(map[string]interface{})for key, value := range params {if find := strings.Contains(isFilterStr, key); !find {data[key] = value}}return data}
- 接下来就是在控制器
controller
中使用封装好的FindAll
获取数据了。 代码如下:
// 获取商品列表信息func GetGoodsList(ctx *gin.Context) {// 获取DB句柄DB := config.InitDB()// 使用获取全部请求参数方法进行:获取参数params, _ := utils.DataMapByRequest(ctx)// 查询数据var goods model.Goods// 使用封装好的FindAllGoodResult, count := goods.FindAll(DB, params)// struct 转 map (反射 reflect包)//data := make(map[string]interface{})//elem := reflect.ValueOf(&goods).Elem()//var relType reflect.Type//for i := 0; i < relType.NumField(); i++ {//data[relType.Field(i).Name] = elem.Field(i).Interface()//}// 返回值utils.Success(ctx, "获取成功", gin.H{"count": count,"data": GoodResult,})}
- 最后一步就是:配置路由。 话不多说,直接上代码:
func Routers(r *gin.Engine) {app := r.Group("/app"){// v1v1 := app.Group("/v1"){// ........ 更多// 管理平台adminGroup := v1.Group("/admin", middleware.CheckToken()){// ........ 更多// 商品goodsGroup := adminGroup.Group("/goods"){goodsGroup.POST("/get-list", controller.GetGoodsList)// ........ 更多}// ........ 更多}}}}