在我去的代码,我经常使用if
这样
if user && user.Registered { }
在去模板等效代码会
{{ if and .User .User.Registered }} {{ end }}
不幸的是在模板代码失败,如果.User
是nil
:/
是否有可能实现去模板是一回事吗?
模板and
功能无法做到像围棋short circuit操作&&
评价。
被称为函数之前的and
函数的参数进行评估。表达.User.Registered
始终评估,即使.User
是零。
解决方法是使用嵌套if
:
{{if .User}}{{if .User.Registered}} {{end}}{{end}}
您可以通过使用模板函数避免嵌套if
或with
:
func isRegistered(u *user) bool {
return u != nil && u.Registered
}
const tmpl = `{{if isRegistered .User}}registered{{else}}not registered{{end}}`
t := template.Must(template.New("").Funcs(template.FuncMap{"isRegistered": isRegistered}).Parse(tmpl))
另一种选择是使用{{with}}
行动,而不是and
模板功能。
从text/template
的包doc引用:
{{with pipeline}} T1 {{end}} If the value of the pipeline is empty, no output is generated; otherwise, dot is set to the value of the pipeline and T1 is executed.
使用{{with}}
往往导致更清洁和更短的代码,如点{{with}}
已经设置到非空“包装”,在我们的例子中.
的.User
内;而且你不必担心如何,如果and
模板函数的参数进行评估。
您的模板重写:
{{with .User -}}
{{if .Registered}}REGISTERED{{end}}
{{- end}}
测试它并没有与用户:
t := template.Must(template.New("").Parse(tmpl))
fmt.Println("No user:")
if err := t.Execute(os.Stdout, nil); err != nil {
panic(err)
}
u := struct{ Registered bool }{true}
fmt.Printf("User: %+v\n", u)
if err := t.Execute(os.Stdout, map[string]interface{}{"User": u}); err != nil {
panic(err)
}
输出(尝试在Go Playground):
No user:
User: {Registered:true}
REGISTERED