beego中分页需手动用querytable的limit和offset实现,配合count查总数、参数校验及封装通用函数;paginator仅负责前端页码渲染,不参与数据库查询。

Beego 中用 QueryTable 做分页查询最直接
Beego 的 ORM(orm 包)本身不提供开箱即用的“分页方法”,但通过 QueryTable 配合 Limit 和 Offset 就能精准控制分页逻辑。关键不是找“分页函数”,而是手动算好偏移量和条数。
常见错误是直接在 QueryTable("user").All(&users) 后再切片,这会把全表查出来再内存分页,数据一多就 OOM 或超时。
- 正确做法:在数据库层用
Limit(n).Offset(offset)限定结果集 -
offset = (page - 1) * pageSize,注意页码通常从 1 开始,别写成page * pageSize - 查总数用
QueryTable("user").Count(),不要用len(users)判断是否还有下一页
分页参数校验和默认值必须自己加
Beego 不自动处理分页参数合法性,page 和 page_size 从 GetString 拿到后全是字符串,不转、不校验就会 panic 或查出意外结果。
典型问题:page=0、page=-1、page_size=10000、page_size=abc —— 这些都会让 QueryTable 报错或拖慢数据库。
- 用
c.GetInt("page", 1)和c.GetInt("page_size", 10)设默认值并转整型 - 手动限制范围:
page = max(1, min(page, 9999)),page_size = max(1, min(page_size, 100)) - 如果参数非法,建议返回 400 并带明确提示,比如
"page must be >= 1"
封装一个通用分页查询函数能少踩很多坑
每次写 Limit/Offset/计数/校验太重复,抽成函数后逻辑集中,也方便统一加日志或监控。
示例结构(不依赖具体 model):
func Paginate(o orm.Ormer, qs orm.QuerySeter, page, pageSize int, v interface{}) (int64, error) {
offset := (page - 1) * pageSize
total, _ := qs.Count()
_, err := o.QueryTable("").SetModel(qs.GetModel()).Limit(pageSize, offset).All(v)
return total, err
}
注意点:
-
qs.GetModel()是获取当前 QuerySeter 绑定的 struct 类型,避免硬编码表名 - 不能直接传
QueryTable("user")进去再调Limit,因为QueryTable返回的是新实例,链式调用需保持同一对象 - 返回
total而不是只查数据,前端才好渲染页码栏
Beego 2.x 的 paginator 包只是辅助渲染,不参与查询
有人看到 Beego 文档里有 paginator 就以为它能自动分页,其实它只是个模板工具:接收总条数、当前页、每页条数,生成上一页/下一页/页码链接 HTML —— 查询逻辑仍得你手写。
容易混淆的点:
-
paginator.NewPaginator(c.Ctx.Request, pageSize, total)的total必须是你自己查出来的,不是传个 QuerySeter 它就帮你算 - 它不碰数据库,也不调
QueryTable,纯前端分页数据准备 - 如果你用的是 Beego 1.x,这个包叫
utils.Paginator,API 略有不同,但定位一致
真正耗资源的是查数据那步,分页器只是最后把数字变成按钮——别指望它替你省 SQL。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











