如何在Golang中实现分页功能_Golang Web分页加载与实现方法

2次阅读

go语言分页需安全解析http参数并校验page≥1、size在1–100间,用OFFSET/LIMIT时注意高偏移性能问题,推荐游标分页;响应应含Total、Page、TotalPages等元信息。

如何在Golang中实现分页功能_Golang Web分页加载与实现方法

Go 语言本身不提供开箱即用的分页组件,但通过组合 database/sql(或 gorm)、HTTP 请求参数解析和结构化响应,能简洁、可控地实现分页——关键不是“用什么库”,而是怎么设计 offset/limit 逻辑和处理边界。

如何从 HTTP 请求中安全提取 page 和 size 参数

用户传来的 pagesize字符串,必须显式校验并转为整数,否则直接用于 SQL 会导致 panic 或注入风险(即使用了预处理,非法值仍可能破坏业务逻辑)。

  • page 应 ≥ 1,0 或负数视为第 1 页;size 建议限制范围(如 1–100),超限则截断或返回错误
  • strconv.ParseInt() 而非 strconv.Atoi(),便于区分空值和格式错误
  • 推荐封装成可复用函数,例如:
    func parsePageQuery(r *http.Request) (page, size int64, err error) {     page, err = strconv.ParseInt(r.URL.Query().Get("page"), 10, 64)     if err != nil || page < 1 {         page = 1     }     size, err = strconv.ParseInt(r.URL.Query().Get("size"), 10, 64)     if err != nil || size < 1 {         size = 10     }     if size > 100 {         size = 100     }     return }

使用 OFFSET/LIMIT 实现数据库分页的注意事项

mysql/postgresql/sqlite 都支持 LIMIT offset, count,但高偏移量(如 OFFSET 100000)性能会急剧下降——数据库仍需扫描并跳过前面所有行。

  • 避免在总记录数未知时盲目用 OFFSET:先查总数(select COUNT(*))再分页,适合中小数据集;大数据量建议用游标分页(基于上一页最后 ID 或时间戳)
  • 计算 offset 时注意:第 1 页对应 offset = 0,公式是 (page - 1) * size,别写成 page * size
  • 若用 gorm,调用 Limit(size).Offset(offset) 即可,但需确保 offset 非负;Limit(0) 会被忽略,Offset(0) 安全

构造带分页元信息的 jsON 响应结构

前端需要知道当前页、总页数、总数、是否有下一页等,不能只返回数据列表。硬编码字段名易出错,建议定义结构体统一序列化。

立即学习go语言免费学习笔记(深入)”;

  • 典型响应结构示例:
    type PageResult[T any] struct {     Data       []T `json:"data"`     Total      int64 `json:"total"`     Page       int64 `json:"page"`     Size       int64 `json:"size"`     TotalPages int64 `json:"total_pages"`     HasNext    bool  `json:"has_next"`     HasPrev    bool  `json:"has_prev"` }
  • TotalPages 计算用 (total + size - 1) / size(向上取整),避免浮点运算
  • HasNext = page * size ,HasPrev = page > 1

真正麻烦的不是写几行 LIMIT,而是当 page=10000 且每页 20 条时,OFFSET 199980 会让查询变慢甚至超时——这时候得切到基于主键或时间戳的游标分页,而不仅仅是改个参数。

text=ZqhQzanResources