【问题标题】:Using custom func in Go condition template在 Go 条件模板中使用自定义函数
【发布时间】:2016-07-26 09:55:29
【问题描述】:

我正在尝试定义一个自定义 Go 函数以在模板条件中使用。 我想要实现的是:如果给定的参数是 IPv4 地址,则模板将输出 IPv4: [argument] 否则它将输出 IPv6: [argument]。 p>

为此,我创建了一个这样的模板:

{{ range .Addresses }}
{{ if IsIPv4 . }}
IPv4: {{ . }}
{{ else }}
IPv6: {{ . }}
{{ end }}
{{ end }}

如您所见,我创建了一个名为 IsIPv4 的新函数,它接受一个字符串参数并给定参数返回真或假。代码如下:

var (
    errNotAnIPAddress = errors.New("The argument is not an IP address")
)

func isIPv4(address string) (bool, error) {
    ip := net.ParseIP(address)

    if ip == nil {
        return false, errNotAnIPAddress
    }

    return (ip.To4() != nil), nil
}

执行我的模板时,我没有遇到任何错误,但是在尝试评估 {{ if IsIPv4 时,执行似乎停止了。 }}

当然,函数是在尝试解析和执行模板之前映射的。

funcMap := template.FuncMap{
    "IsIPv4": isIPv4,
}

我对 Go 很陌生,我可能错过了一些东西(可能很明显?)。

为了稍微调试一下,我尝试在模板中删除 IsIPv4 调用,给出类似 {{ if 的条件。 }}。结果总是输出IPv4:[IP 地址]。这对我来说很有意义。

我还查看了预定义的 Go 函数,例如 eq,看起来我正在尝试重现相同的想法,但没有任何成功。

【问题讨论】:

  • 您是否将函数映射funcMap 添加到模板中?您需要调用模板的Funcs 方法来执行此操作。详情:golang.org/pkg/text/template/#Template.Funcs
  • @abhink 我当然做到了。否则它会告诉我在解析模板时没有定义函数。

标签: function templates go


【解决方案1】:

TL;DR;您必须检查template.Execute()template.ExecuteTemplate() 返回的error 值,它会告诉您为什么它不适合您。


可能出错的地方

首先,您的执行不会恐慌,因为它只是返回一个错误。如果你检查一下,你可能会立即知道出了什么问题:

if err := t.Execute(os.Stdout, data); err != nil {
    panic(err)
}

接下来会出现什么问题:您必须在解析模板之前注册自定义函数,因为模板引擎需要能够静态分析模板,并且它需要事先知道@ 987654329@是一个函数名:

t := template.Must(template.New("").Funcs(template.FuncMap{
    "IsIPv4": isIPv4,
}).Parse(templ))

另一个潜在的错误是isIPv4() 需要string 类型的值,而您可能会传递不同类型的值。

如果您打算停止执行模板,则为模板注册的自定义函数只应返回非nil 错误。因为如果您返回 error,就会发生这种情况。 template.FuncMap:

[...] 如果在执行期间第二个(错误)返回值的计算结果为非零,则执行终止并且 Execute 返回该错误。

工作示例

这是一个使用您的模板和isIPv4() 函数的工作示例:

t := template.Must(template.New("").Funcs(template.FuncMap{
    "IsIPv4": isIPv4,
}).Parse(templ))

m := map[string]interface{}{
    "Addresses": []string{"127.0.0.1", "0:0:0:0:0:0:0:1"},
}

if err := t.Execute(os.Stdout, m); err != nil {
    panic(err)
}

输出(在Go Playground上试试):

IPv4: 127.0.0.1

IPv6: 0:0:0:0:0:0:0:1

潜在错误

上述程序打印以下错误:

传递一个无效的IP:

    "Addresses": []string{"127.0.0.1.9"},

输出:

panic: template: :2:6: executing "" at <IsIPv4 .>: error calling IsIPv4:
    The argument is not an IP address

传递非string 值:

    "Addresses": []interface{}{2},

输出:

panic: template: :2:13: executing "" at <.>: wrong type for value; expected string; got int

在模板被解析后尝试注册您的自定义函数:

t := template.Must(template.New("").Parse(templ))
t.Funcs(template.FuncMap{
    "IsIPv4": isIPv4,
})

输出:

panic: template: :2: function "IsIPv4" not defined

【讨论】:

  • 好的,我明白了。感谢您提供非常详细的答案,它实际上回答了我的问题。我在执行模板时确实出错了。 at &lt;.&gt;: wrong type for value; expected string; got net.IP 意思是我已经有一个 net.IP 结构而不是一个字符串,所以我的函数不起作用。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多