If statement Golang模板变量isset

If statement Golang模板变量isset,if-statement,go,struct,go-templates,If Statement,Go,Struct,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 := templa

我创建了一个函数来检查是否定义了变量:

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)
在模板中,我有:

{{ if isset .Email }}
    email is set
{{ end }}
如果变量包含在
templateData
(这是一个包含映射和字符串的自定义结构)中,则此函数可以工作,但如果变量不存在,则会出现错误

错误是:

executing "header" at <.Email>: can't evaluate field Email in type base.customData
在执行“header”时:无法计算base.customData类型中的字段Email
在我的例子中,“base.go”是处理程序,“customData”由以下内容定义:
type customData struct{..}

我希望能够重用模板,并且仅当一些变量从处理程序发送时才显示某些部分。知道如何在模板端实现变量
isset
检查吗

我还尝试使用:
{{{if.Email}}do stuff{{end}}
,但这也给了我同样的错误


有什么想法吗?

如果不向模板发送包含变量的数据,但使用
{{If.variable}
则会出现错误:

在以下位置执行“templatename”:无法计算类型处理程序.Data中的字段变量

我的解决方案是将“Email”变量作为布尔值(false)发送,以便通过
{{if.Email}
函数检查。但这是我不喜欢的短期解决方案

我的灵感来自:。在该示例中,它们为经过身份验证和未经身份验证的用户显示了不同的HTML。您将看到,在这两种情况下,它们都发送“Logged”变量。尝试从结构中删除该变量并执行该函数。您将收到我上面提到的错误。

推荐的方法 首先,推荐的方法是不依赖于结构字段是否存在。当然,模板可能有可选部分,但决定是否渲染部分的条件应取决于所有情况下都存在的字段

问题,并使用地图避免它 如果模板数据的类型是
结构(或指向结构的指针),并且没有具有给定名称的字段或方法,模板引擎将为此返回一个错误

如果要使用映射,可以很容易地消除此错误,因为映射可以使用不包含的键进行索引,其结果是值类型(而不是错误)

要进行演示,请参见此示例:

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{}{})
输出(在上尝试):

使用它的示例:

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{}{})
输出(在上尝试):


简单的方法是:

{{ if .Email }}
是使用索引:

{{ if index . "Email" }}

尝试在
isset
函数中记录
a
。你看到你在传递什么了吗?如果不是,则在模板级别存在问题。也许可以尝试同时传入结构和键来访问它,以检查是否设置了isset,并相应地修改您的函数以接受这两个参数。如果我的结构包含“Email”,它将工作,并将其记录在isset函数中。如果结构不包含“Email”(这是我的例子),它只会输出上面的错误,不会显示来自issset函数的日志。PHP有isset($variable)函数,它返回true/false,GO呢?如何检查模板中的变量以查看它是否从处理程序发送?例如,我只想在用户登录时显示一个菜单。只需尝试
{{if.Email}}
,这应该对您有效。看一看。如果映射中条目的值为“false”(即它打印“Email未设置”。而不是“Email is:false”),则映射方法不起作用。我看不出这是如何工作的。请解释一下?AFAICT索引将在非可枚举项上出错
索引
函数不适用于类型
结构
Filled struct:
  Email is: as@as.com
Empty struct:
  Email is unavailable.
{{ if .Email }}
{{ if index . "Email" }}