
在 Go 模板中,eq 是前缀函数(非中缀操作符),必须将比较的两个值作为独立参数传入;若错误地写成 (index $n 0) eq (index $n 1),模板引擎会将其解析为“先执行 (index $n 0),再尝试对结果调用方法 eq”,导致逻辑失效。
在 go 模板中,`eq` 是前缀函数(非中缀操作符),必须将比较的两个值作为独立参数传入;若错误地写成 `(index $n 0) eq (index $n 1)`,模板引擎会将其解析为“先执行 `(index $n 0)`,再尝试对结果调用方法 `eq`”,导致逻辑失效。
Go 模板语法严格区分函数调用与操作符——它没有中缀比较运算符(如 == 或 eq 不能像 a eq b 这样写成“中缀形式”)。所有比较函数(包括 eq, ne, lt, gt 等)均为函数式调用,需以 {{eq arg1 arg2}} 形式书写。
你原始模板中的问题代码:
{{if (index $n 0) eq (index $n 1)}}={{else}}!={{end}}会被模板解析器理解为:
→ 先求值 (index $n 0)(例如 1),
→ 然后试图在该结果(整数 1)上调用名为 eq 的字段或方法(不存在),
→ 最终因无此方法而静默返回 false(或空值),导致 if 分支始终不成立,else 分支恒执行 → 所有行都输出 =。
✅ 正确写法是将 eq 作为顶层函数,显式传入两个参数:
{{if eq (index $n 0) (index $n 1)}}={{else}}!={{end}}完整修复后的模板如下:
package main
import (
"os"
"text/template"
)
func main() {
const myTemplate = `
{{range $n := .}}
{{index $n 0}} {{if eq (index $n 0) (index $n 1)}}={{else}}!={{end}} {{index $n 1}}
{{end}}
`
t := template.Must(template.New("").Parse(myTemplate))
t.Execute(os.Stdout,
[][2]int{
[2]int{1, 2},
[2]int{2, 2},
[2]int{4, 2},
})
}运行输出即为预期结果:
1 != 2 2 = 2 4 != 2
? 提示与注意事项:
- 所有比较函数(eq, ne, lt, le, gt, ge)均遵循相同规则:{{eq a b}},不可颠倒或中缀化;
- 参数支持嵌套函数调用(如 {{eq (index . 0) (len .)}}),但括号必须匹配、语义清晰;
- 若比较涉及可能为 nil 的值(如 map 查找或指针解引用),建议先用 isset 或 default 防御性处理,避免模板 panic;
- 调试技巧:可临时使用 {{printf "%#v" (index $n 0)}} 输出中间值,验证数据是否符合预期。
掌握这一前缀函数范式,是写出健壮 Go 模板的关键基础。


















