去模板和功能

问题描述 投票:5回答:2

在我去的代码,我经常使用if这样

if user && user.Registered { }

在去模板等效代码会

{{ if and .User .User.Registered }} {{ end }}

不幸的是在模板代码失败,如果.Usernil:/

是否有可能实现去模板是一回事吗?

go go-templates
2个回答
11
投票

模板and功能无法做到像围棋short circuit操作&&评价。

被称为函数之前的and函数的参数进行评估。表达.User.Registered始终评估,即使.User是零。

解决方法是使用嵌套if

 {{if .User}}{{if .User.Registered}}  {{end}}{{end}}

您可以通过使用模板函数避免嵌套ifwith

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))

playground example


3
投票

另一种选择是使用{{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
© www.soinside.com 2019 - 2024. All rights reserved.