Gin模板中需用{{range $index, $item := .Data}}配合{{if eq (mod $index 2) 0}}判断奇偶行实现隔行变色,推荐手写class而非依赖Bootstrap或CSS :nth-of-type,复杂逻辑应前置到handler预处理。

模板里用 index 或 $index 判断奇偶行
Gin 默认使用 Go 的 html/template,不支持 CSS 的 :nth-child 直接绑定到数据循环中(因为服务端渲染时浏览器还没解析 CSS)。必须在模板内手动判断当前是第几行。最常用的是 range 的带索引形式:{{range $index, $item := .Data}},然后用 {{$index | mod 2}} 得到余数。
注意:mod 是 Go template 内置函数,但只在 Go 1.19+ 原生支持;旧版 Gin(如 v1.9.x)若用的是低版本 Go 运行时,mod 可能不存在,此时得提前在 template.FuncMap 中注册一个自定义函数。
- 推荐写法(兼容性好):
{{if eq (mod $index 2) 0}}bg-light{{else}}bg-dark{{end}} - 别写成
{{if $index % 2 == 0}}—— template 语法不支持%运算符 - 索引从 0 开始,所以第 1 行是偶数行(
$index = 0),符合多数人预期
table 标签内用 tr 的 class 控制样式
隔行变色本质是给每行 <tr> 加不同 class,再由 CSS 定义背景色。不要试图在 <td> 里重复写样式,更不要用内联 style 手动写死——既难维护,又破坏语义。
示例片段:
{{range $i, $user := .Users}}
<tr class="{{if eq (mod $i 2) 0}}table-row-even{{else}}table-row-odd{{end}}">
<td>{{$user.Name}}</td>
<td>{{$user.Age}}</td>
</tr>
{{end}}
CSS 部分只需简单定义:
.table-row-even { background-color: #f8f9fa; }
.table-row-odd { background-color: #e9ecef; }
- 避免用
!important覆盖 Bootstrap 的.table-striped—— Gin 模板和 Bootstrap CSS 是两层事,混用易冲突 - 如果已引入 Bootstrap,直接用
<table class="table table-striped">最省事,但该样式只对 tbody 内的奇数行生效,且无法自定义颜色 - 手写 class 更可控,尤其当需要适配深色模式或品牌色时
用 CSS :nth-of-type 替代服务端判断?小心 DOM 结构干扰
有人想绕过模板逻辑,纯靠 CSS 实现,比如写 tr:nth-of-type(odd) { background: #eee; }。这确实可行,但有个硬伤:只要 <tr> 前面有其他同级 <tr>(比如表头 <thead><tr>...</tr></thead> 或空行、合并单元格的 <tr>),序号就会错位。
- 确保
tbody显式包裹数据行:<tbody>{{range ...}}<tr>...</tr>{{end}}</tbody> - 避免在循环外手动插入
<tr>,否则:nth-of-type会把它们一起计数 - 如果用了
colspan或rowspan,CSS 方案基本失效,必须回到服务端判断
性能与可读性取舍:复杂条件建议提前提取
当隔行逻辑变复杂(比如“每 3 行一循环”“偶数行高亮,但管理员行永远蓝色”),模板里堆 {{if}}{{else if}}{{end}} 会让 HTML 难以阅读,也容易出错。
更稳妥的做法是在 handler 里预处理数据:
- 给每个 item 加字段:
RowClass: "row-even"或IsAdminRow: true - 或传入一个辅助 slice:
RowClasses: []string{"even", "odd", "even", ...} - 模板里就变成干净的:
<tr class="{{$item.RowClass}}">
这种写法牺牲一点内存(多存几个字符串),换来模板清晰、逻辑集中、测试友好。真遇到上万行表格时,服务端预计算反而比每次模板执行一堆判断更快。
真正容易被忽略的是:隔行样式在打印 PDF 或导出 Excel 时通常不生效,如果业务要求导出结果也保持交替色,那必须在生成阶段(比如用 excelize)单独处理,不能只依赖前端或模板渲染。


















