在我去的代码,我经常使用if
这样转到模板和功能
if user && user.Registered { }
在去模板等效代码将
{{ if and .User .User.Registered }} {{ end }}
不幸的是在模板代码失败,如果.User
是nil
:/
在go模板中可以实现同样的功能吗?
在我去的代码,我经常使用if
这样转到模板和功能
if user && user.Registered { }
在去模板等效代码将
{{ if and .User .User.Registered }} {{ end }}
不幸的是在模板代码失败,如果.User
是nil
:/
在go模板中可以实现同样的功能吗?
模板and
函数不会做short circuit评估像Go &&
运算符。
and
函数的参数在函数调用之前进行求值。总是评估表达式.User.Registered
,即使.User
为零。
解决方法是使用嵌套if
:
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))
另一种选择是使用:
{{if .User}}{{if .UserRegistered}} {{end}}{{end}}
您可以通过使用模板函数避免嵌套if
或with
{{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
我想使用嵌套ifs进行转义..因为它会在 – Goranek
之间重复太多的模板代码,即使这并非我真正接受的解决方案。 – Goranek