防溢出分页
说明
pagination 统一把一基页码转换为数据库偏移和安全的内存切片边界。它保证非法值或极大输入不会发生整数回绕,避免错误地落回第一页或生成非法切片区间。本包没有配置、状态、I/O 或 HTTP 路由。
对外接口
Offset(page, size int) int返回非负数据库偏移。页码不大于一或页大小非正时返回零;若乘法会超过当前平台的 int,则返回最大 int,让结果继续表示越界位置而不是回绕到零附近。网关编解码和列表处理在数据库查询前调用它。Bounds(total, page, size int) (start, end int)返回内存列表的半开区间。总数或页大小非正时返回空区间;页码小于一时按第一页处理;页码超出数据时两个边界都返回 total;正常情况下 end 不超过 total。当 total 与列表长度一致时,调用方可安全切片。
两个函数都不返回错误,也不修改输入。调用方仍需限制公开接口允许的最大页大小,并确保 total 与被切片列表一致。
内部核心实现
Offset 先取得最大 int,比较 page 减一与 max 除以 size,证明安全后才相乘。Bounds 先判断 page 减一是否大于 total 减一除以 size,只有未越界才计算乘积;末尾先比较页大小与剩余元素数,再做加法。分阶段比较构成溢出边界,没有未经检查的用户输入乘法。
测试依赖
page_test.go 覆盖普通分页、非法值、越界页和会导致溢出的极大输入。运行 go test ./internal/util -count=1;不依赖外部服务。
源码职责与入口
- page.go 是全部生产实现。Offset 是 SQL 分页入口,Bounds 是内存切片入口。
- page_test.go 验证归一化、半开区间和防溢出行为。