跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何使用Golang处理分页查询功能_Golang分页数据查询与优化

分页查询必须传 page 和 size 并校验:page<1 设为 1,size 限 1–100;须用 ORDER BY 保证稳定性,推荐游标分页;GORM 中 Count 需隔离条件;大数据量应避 OFFSET 改用游标或覆盖索引。 分页查询必须传
page
和
size
,不能只靠 前端 传偏移量 后端自己算
offset
容易出错,尤其当
page
为 0 或负数、
size
超过上限时,数据库可能直接报错或返回空结果。Golang 中应统一校验并转换:
page
默认为 1,小于 1 则设为 1
size
应限制范围(如 1–100),超出则截断或返回错误 用
offset = (page - 1) * size
计算,避免前端恶意传大偏移量导致慢查询 示例片段:
if page < 1 { page = 1 } if size < 1 || size > 100 { size = 20 } offset := (page - 1) * size
用
sql.DB.Query
做分页时,务必加
ORDER BY
MySQL / PostgreSQL 等对无序分页不保证稳定性:同一查询多次执行可能因索引顺序、MVCC 版本不同而跳过或重复记录。尤其在高并发写入场景下,漏数据很常见。 没有
ORDER BY
的
LIMIT OFFSET
不是真正分页,只是“取前 N 条” 推荐用主键或唯一时间字段排序,例如
ORDER BY id ASC
或
ORDER BY created_at DESC, id DESC
若业务允许,优先考虑游标分页(
WHERE created_at < ? AND id < ?
),避免
OFFSET
性能衰减 用
gorm
时,
Limit
/
Offset
不会自动处理总数,需手动
COUNT(*)
gorm
的
Limit
+
Offset
只负责查数据,不附带总条数。但多数分页 UI 需要显示“共 XX 条”“第 X 页”。别用
db.Count(&total)
直接套在带
WHERE
的链式查询上——它会忽略
Order
、
Joins
甚至部分
Where
条件。 立即学习 “ go语言免费学习笔记(深入) ”; 正确做法:拆成两个查询,或用子查询封装条件 简单场景可用
db.Session(&gorm.Session{NewDB: true}).Model(&User{}).Where(...).Count(&total)
防止复用原 query 的 limit/offset 复杂关联查询建议手写
SELECT COUNT(*) FROM (SELECT ... ) AS t
,用
Raw
执行,更可控 大数据 量下
OFFSET
分页变慢?换游标或覆盖索引 当
OFFSET
超过 10 万行,MySQL 可能扫描并丢弃大量数据,响应从毫秒升到秒级。这不是 Golang 层能优化的,得从 SQL 和索引入手。 游标分页要求前端传上一页最后一条的排序字段值(如
last_created_at
),SQL 改为
WHERE created_at < ? ORDER BY created_at DESC LIMIT 20
确保排序字段有索引;若用多字段排序(如
ORDER BY status, created_at
),索引必须包含全部字段且顺序一致 避免
SELECT *
,只查必要字段,减少网络和内存开销;大文本字段(如
TEXT
)可单独 异步加载 游标分页不能跳页,但对“下一页”“上一页”场景足够高效,也规避了
OFFSET
的偏移漂移问题。

相关文章