Go模板中if不支持&&、||等运算符,需用嵌套if或预处理逻辑;比较须用gt/lt/eq等函数;nil slice与空slice在if中均判false,安全判断应使用len;自定义函数需注册到FuncMap且签名严格匹配。

Go template 里 if 语句怎么写才不报错
Go 模板的 if 不是 Go 语言本身的 if,它只支持表达式求值,不支持赋值、函数调用(除非注册)、复合逻辑运算符(如 &&、||)。常见错误是直接照搬 Go 写法:{{ if .User.Name != "" && .User.Age > 18 }} —— 这会 panic,因为模板语法不认 &&。
正确做法是把复杂判断提前在 Go 代码中完成,或用嵌套 if + else if 拆解:
{{ if .User.Name }}
{{ if gt .User.Age 18 }}
成年用户
{{ else }}
未成年用户
{{ end }}
{{ else }}
用户名为空
{{ end }}-
gt、lt、eq等比较函数必须显式调用,不能用符号 - 空值(nil、""、0、false、nil slice/map)在
if中自动判为 false,但要注意指针字段未初始化时是 nil,不是空字符串 - 模板里没有 else-if 关键字,得用
{{ else if ... }}连写(注意中间没空格)
为什么 {{ if .Items }} 有时不生效
这通常是因为 .Items 是 nil slice,而 Go 模板对 nil slice 和空 slice 的处理一致:都为 false。但如果你传的是 *[]string(指向 slice 的指针),且该指针为 nil,那 {{ if .Items }} 判的是指针是否为 nil,不是底层数组 —— 容易误判。
安全做法是统一用 len 显式判断长度:
立即学习“go语言免费学习笔记(深入)”;
{{ if gt (len .Items) 0 }}
<ul>
{{ range .Items }}
<li>{{ . }}</li>
{{ end }}
</ul>
{{ else }}
<p>暂无数据</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/ai/1627" title="一览妙笔"><img
src="https://img.php.cn/upload/ai_manual/000/000/000/175680271143118.png" alt="一览妙笔" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/ai/1627" title="一览妙笔">一览妙笔</a>
<p>自媒体、编剧、营销人员写作工具</p>
</div>
<a href="/ai/1627" title="一览妙笔" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
{{ end }}- 所有内置函数(
len、print、urlquery等)都必须加括号调用 -
range自动处理 nil slice,不会 panic,但if不会帮你做 len 判断 - 如果结构体字段是
sql.NullString这类类型,需先访问.String或判断.Valid,否则if只看整个 struct 是否零值
template.FuncMap 怎么加自定义判断函数
想写 {{ if hasRole .User "admin" }}?必须先注册函数到 template.FuncMap,否则模板解析就失败。
注册时函数签名必须严格匹配:单个返回值(或两个,第二个是 error),参数类型明确:
funcMap := template.FuncMap{
"hasRole": func(u User, role string) bool {
for _, r := range u.Roles {
if r == role {
return true
}
}
return false
},
}
t := template.New("page").Funcs(funcMap)- 函数名首字母小写也能注册,但模板里调用时仍用小写(Go 模板不区分导出性)
- 函数体内不能 panic,否则整个模板执行中断;建议用
recover包一层或提前校验参数 - 避免在 FuncMap 里做耗时操作(如 DB 查询),模板执行是同步阻塞的
嵌套 if 导致缩进混乱怎么办
模板不是代码,没有作用域概念,{{ end }} 必须和最近的 {{ if }} 配对。多层嵌套时容易漏写或错位,导致解析失败或逻辑错乱 —— 错误信息通常是 unexpected "end" in if 或 unclosed action。
推荐用编辑器高亮 + 手动缩进对齐(别依赖自动格式化,Go 模板没有标准 formatter):
{{ if .A }}
A 存在
{{ if .B }}
B 也存在
{{ if .C }}
C 也存在
{{ end }}
{{ end }}
{{ else }}
A 不存在
{{ end }}- 每行
{{和}}尽量独占一行,尤其if/range/end,方便肉眼配对 - 不要混用
{{- if}}和{{if -}}去除空白,除非你清楚每处换行是否影响 HTML 渲染 - 复杂逻辑优先拆成多个子模板(
{{ define "xxx" }}),比硬塞一堆嵌套更易维护
最常被忽略的是:模板里的变量作用域是动态的,{{ with .User }} 会改变 . 的指向,之后所有 .Name 都是 .User.Name,但 {{ end }} 后又恢复原 . —— 这个隐式切换很容易在嵌套中搞丢上下文。









