Pas*_*cut 7 struct if-statement go go-templates
我创建了一个函数来检查是否定义了变量:
fm["isset"] = func(a interface{}) bool {
if a == nil || a == "" || a == 0 {
fmt.Println("is not set")
return false
}
fmt.Println("is set")
return false
}
tmpl := template.Must(template.New("").Funcs(fm).ParseFiles("templates/header.html"))
err := tmpl.ExecuteTemplate(w, "header", templateData)
Run Code Online (Sandbox Code Playgroud)
在模板中我有:
{{ if isset .Email }}
email is set
{{ end }}
Run Code Online (Sandbox Code Playgroud)
如果变量包含在templateData(它是包含映射和字符串的自定义结构)中,则此函数有效,但如果变量不存在则会给出错误.
错误是:
executing "header" at <.Email>: can't evaluate field Email in type base.customData
Run Code Online (Sandbox Code Playgroud)
在我的情况下,"base.go"是处理程序,"customData"由以下内容定义:type customData struct{..}.
我希望能够重用模板,并且只有在从处理程序发送一些变量时才显示某些部分.任何想法如何isset在模板端实现变量检查?
我也试过使用:{{ if .Email}} do stuff {{ end }}但这也给了我同样的错误.
任何的想法?
首先,推荐的方法是不依赖于是否存在struct字段.当然,模板可能有可选部分,但决定是否渲染零件的条件应该依赖于所有情况下都存在的字段.
如果模板数据的类型是struct(或指向结构的指针)并且没有具有给定名称的字段或方法,则模板引擎会为此返回错误.
如果您要使用地图,则可以轻松摆脱此错误,因为地图可以使用不包含的键进行索引,并且该索引表达式的结果是值类型的零值(而不是错误) .
要演示,请参阅此示例:
s := `{{if .Email}}Email is: {{.Email}}{{else}}Email is NOT set.{{end}}`
t := template.Must(template.New("").Parse(s))
exec := func(name string, param interface{}) {
fmt.Printf("\n%s:\n ", name)
if err := t.Execute(os.Stdout, param); err != nil {
fmt.Println("Error:", err)
}
}
exec("Filled map", map[string]interface{}{"Email": "as@as"})
exec("Empty map", map[string]interface{}{})
exec("Filled struct", struct {
Email string
}{Email: "as@as.com"})
exec("Empty struct", struct{}{})
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
Filled map:
Email is: as@as
Empty map:
Email is NOT set.
Filled struct:
Email is: as@as.com
Empty struct:
Error: template: :1:5: executing "" at <.Email>: can't evaluate field Email in type struct {}
Run Code Online (Sandbox Code Playgroud)
struct并提供"isset"如果你必须或想要坚持struct,这个"isset"可以实现和提供,我会称之为avail().
此实现使用反射,并且为了检查其名称给出的字段是否存在(可用),还必须将(包装器)数据传递给它:
func avail(name string, data interface{}) bool {
v := reflect.ValueOf(data)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return false
}
return v.FieldByName(name).IsValid()
}
Run Code Online (Sandbox Code Playgroud)
使用它的示例:
s := `{{if (avail "Email" .)}}Email is: {{.Email}}{{else}}Email is unavailable.{{end}}`
t := template.Must(template.New("").Funcs(template.FuncMap{
"avail": avail,
}).Parse(s))
exec := func(name string, param interface{}) {
fmt.Printf("\n%s:\n ", name)
if err := t.Execute(os.Stdout, param); err != nil {
fmt.Println("Error:", err)
}
}
exec("Filled struct", struct {
Email string
}{Email: "as@as.com"})
exec("Empty struct", struct{}{})
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上试试):
Filled struct:
Email is: as@as.com
Empty struct:
Email is unavailable.
Run Code Online (Sandbox Code Playgroud)