gin分页需后端计算currentpage、totalpages、pageurl并传入模板,模板用range遍历页码,{{if eq .currentpage $i}}高亮当前页,范围建议±2且处理边界;pageurl须以?或&结尾,首尾页及省略号靠条件判断实现。

模板里怎么生成带当前页高亮的页码列表
Gin 本身不处理分页渲染,得靠你在 html/template 里手写逻辑。核心是传入三个关键变量:currentPage、totalPages、pageURL(比如 /posts?page=),然后用 range 遍历页码,对 currentPage 做特殊标记。
常见错误是硬写死 1~10 页,结果总页数只有 3 页还显示到 10,或者没处理边界(比如当前页是 1,左边不该出现省略号)。
- 页码范围建议控制在「当前页 ±2」,最多展示 5 个数字页码 + 两侧省略号
- 用
{{if eq .CurrentPage $i}}判断高亮,别用==(Go 模板不支持) -
pageURL必须以?或&结尾,否则拼接page=2会出错;更稳妥的做法是传完整 URL 前缀,比如/posts?page=
后端怎么把分页数据塞进模板
Gin 的 c.HTML() 只负责传 map,分页逻辑全在 handler 里算好。你得自己从 query 参数取 page,校验范围,再算出 offset 去查数据库——框架不帮你干这个。
容易漏掉的是边界保护:比如用户手动输 ?page=9999,而实际只有 12 页,这时 currentPage 应该 fallback 到 totalPages,而不是让 SQL offset 越界或返回空列表。
- 用
c.DefaultQuery("page", "1")获取参数,再转成 int 并限制最小为 1 -
totalPages = (totalRecords + pageSize - 1) / pageSize,别用浮点除法再math.Ceil(整数运算更稳) - 传给模板的字段名保持简单,比如
"CurrentPage"、"TotalPages"、"PageURL",避免嵌套结构增加模板复杂度
模板里怎么写省略号和首尾页链接
纯靠 if 判断:当前页 > 3 时显示「首页」和左省略号;当前页
典型翻车点是省略号位置写反,比如 {{if gt .CurrentPage 3}} 后直接写 1 ...,但忘了判断 .CurrentPage 是否大于 3 才该显示「...」前的页码 2 和 3。
- 首页固定为
@#@#@#@#@#@#@#@#@#@0,不是{{.PageURL}}{{.FirstPage}} - 左省略号触发条件:
{{if gt .CurrentPage 3}},右省略号:{{if lt .CurrentPage | sub .TotalPages 2}}(需提前定义sub函数或在后端算好showLastDot) - 推荐在后端预计算好页码切片(如
[]int{1,2,0,10,11},0 表示省略号),模板里只 range 渲染,逻辑更清晰
为什么点击页码后 URL 参数会叠加?
这是 query 参数拼接方式错了。如果 PageURL 是 /posts?,但用户当前 URL 是 /posts?tag=golang&page=1,直接拼 /posts?page=2 会丢掉 tag。真实场景要保留原有参数,只替换 page 值。
最简单的解法是:后端不传 PageURL,改传一个 func(page int) string,但 html/template 不支持调用函数。所以得在 handler 里把完整 URL(含所有 query)解析出来,生成每个页码对应的新 URL。
- 用
url.Parse(c.Request.URL.String())拿原始 URL - 用
url.Values替换page键,再拼回去:u.RawQuery = values.Encode() - 如果不想搞 URL 解析,就要求前端路由用 path 参数(如
/posts/page/2),这样PageURL可固定为/posts/page/,拼接安全
动态分页页码看着小,但 URL 保活、边界裁剪、模板可读性三块都容易出隐性 bug,尤其是多参数场景下,别图省事硬拼字符串。











