在我的go代码中,我经常使用if
这样的
if user && user.Registered { }
go模板中的等效代码将是
{{ if and .User .User.Registered }} {{ end }}
如果.User
为nil
:/
是否可以在go模板中实现相同的功能?
答案 0 :(得分:11)
模板and
功能不像Go &&
运算符那样进行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))
答案 1 :(得分:3)
另一种选择是使用{{with}}
操作而不是and
模板功能。
引自text/template
的包文档:
{{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