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 定义背景色。不要试图在 <code><td> 里重复写样式,更不要用内联 <code>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 内的奇数行生效,且无法自定义颜色 <li>手写 class 更可控,尤其当需要适配深色模式或品牌色时</li> <h3>用 CSS <code>:nth-of-type替代服务端判断?小心 DOM 结构干扰有人想绕过模板逻辑,纯靠 CSS 实现,比如写
tr:nth-of-type(odd) { background: #eee; }。这确实可行,但有个硬伤:只要<tr> 前面有其他同级 <code><tr>(比如表头 <code><thead><tr>...</tr></thead>或空行、合并单元格的<tr>),序号就会错位。 <ul> <li>确保 <code>tbody显式包裹数据行:<tbody>{{range ...}}<tr>...</tr>{{end}}</tbody> - 避免在循环外手动插入
<tr>,否则 <code>:nth-of-type会把它们一起计数 - 如果用了
colspan或rowspan,CSS 方案基本失效,必须回到服务端判断 - 给每个 item 加字段:
RowClass: "row-even"或IsAdminRow: true - 或传入一个辅助 slice:
RowClasses: []string{"even", "odd", "even", ...} - 模板里就变成干净的:
<tr class="{{$item.RowClass}}"> <p>这种写法牺牲一点内存(多存几个字符串),换来模板清晰、逻辑集中、测试友好。真遇到上万行表格时,服务端预计算反而比每次模板执行一堆判断更快。</p> <p>真正容易被忽略的是:隔行样式在打印 PDF 或导出 Excel 时通常不生效,如果业务要求导出结果也保持交替色,那必须在生成阶段(比如用 <code>excelize)单独处理,不能只依赖前端或模板渲染。
性能与可读性取舍:复杂条件建议提前提取
当隔行逻辑变复杂(比如“每 3 行一循环”“偶数行高亮,但管理员行永远蓝色”),模板里堆 {{if}}{{else if}}{{end}} 会让 HTML 难以阅读,也容易出错。
更稳妥的做法是在 handler 里预处理数据:











