go api分页需强制校验page/size并设默认值、必须带确定性order by、count(*)需独立db实例、大数据量应切游标分页;四步缺一不可,否则易致数据错乱或雪崩。

Go API 分页不能只靠 page 和 size 往数据库一塞就完事——不校验会 panic,不加 ORDER BY 会漏数据,硬查 COUNT(*) 在高并发下直接拖垮 DB。
分页参数必须强制校验并设默认值
前端传的 page=0、size=abc、size=999999 都不是“异常”,而是常态。你不拦,GORM 就会把 OFFSET -20 或超大 LIMIT 直接发给 MySQL,轻则空结果,重则触发 ERROR 1235 或连接池耗尽。
-
page小于 1 时,直接赋值为 1(别返回错误,用户点错页码不是 bug) -
size必须硬限制在 1–100 区间,超出就截断为 20(防 DOS,也避免前端误传) - 用
strconv.Atoi转前先判空:r.URL.Query().Get("page") == ""→ 设默认;非数字字符串也要兜住,不能让err != nil泄露到上层 - 别依赖
http.ParseForm():它对重复 key(如page=1&page=2)只取第一个,而有些 SDK 会自动拼多个同名参数
SQL 分页必须带确定性 ORDER BY
没 ORDER BY 的 LIMIT/OFFSET 是伪分页。MySQL 不保证无序查询的行顺序,尤其在有并发 INSERT/UPDATE 时,同一页可能漏掉或重复某条记录。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 排序字段必须有索引,优先选主键
id ASC或带索引的时间字段created_at DESC - 避免单用
created_at:毫秒级相同时间戳很常见,加二级排序如id DESC确保唯一性 - 绝对不要写
ORDER BY RAND():无法翻页,且全表扫描,QPS 上百就卡死 - GORM 中必须显式调用
.Order("id ASC"),不能指望模型定义里的gorm:"primaryKey"自动生效
总数统计(total)不能和分页共用同一个 *gorm.DB 实例
这是 GORM 最隐蔽的坑:db.Where(...).Limit(10).Offset(20).Count(&total) 返回的 total 是 10,不是符合条件的总条数——因为 Count() 会复用前面链式调用的 LIMIT 和 OFFSET。
- 正确做法是新开 session:
db.Session(&gorm.Session{NewDB: true}).Model(&User{}).Where(...).Count(&total) - 复杂 JOIN 查询时,
Count()容易出错,直接手写子查询更稳:db.Raw("SELECT COUNT(*) FROM (SELECT 1 FROM users u JOIN profiles p ON u.id = p.user_id WHERE ...) AS t").Scan(&total) - 大数据量下,
COUNT(*)本身是性能瓶颈,可改用近似值(如EXPLAIN SELECT ...的rows字段)或异步更新的统计表 - 如果业务允许(如信息流“加载更多”),可只查
size + 1条,用len(results) > size判断has_next,彻底省掉COUNT
大数据量必须切换游标分页,不能硬扛 OFFSET
当 OFFSET 超过 10 万,MySQL 就得扫描并丢弃前 N 行,响应从 20ms 暴涨到 2s+。这不是 Go 层能优化的,得换思路。
- 游标必须基于唯一有序字段:主键
id或组合(created_at, id),且该字段要有联合索引 - 前端传
?cursor=123456,后端生成WHERE id (注意方向要和排序一致) -
cursor值不加密,但建议 base64 编码后传输,避免 URL 中出现特殊字符;解码逻辑放在 HTTP handler,Paginator 结构体里只存原始int64或string - 游标模式下,响应中不要返回
page和total,只返回data、has_next和下一个cursor(即当前页最后一条的id)
最常被忽略的一点:分页逻辑看似简单,但校验、排序、计数、游标编码这四步,任何一步脱节都会导致线上数据错乱或接口雪崩。宁愿多写几行校验,也不要相信“前端传的都是合法的”。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










