在Go条件模板中使用自定义func

时间:2016-07-26 09:55:29

标签: function templates go

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

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

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

正如您所看到的,我创建了一个名为 IsIPv4 的新函数,它接受一个字符串参数并给出参数返回true或false。这是代码:

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 ,看起来我试图重现同样的想法,没有任何成功。

1 个答案:

答案 0 :(得分:1)

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

可能出错的事情

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

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

接下来可能出现的问题是:您必须先注册自定义函数 来解析模板,因为模板引擎需要能够静态分析模板,并且需要事先了解{ {1}}是一个函数名称:

IsIPv4

另一个潜在错误是t := template.Must(template.New("").Funcs(template.FuncMap{ "IsIPv4": isIPv4, }).Parse(templ)) 期望值为isIPv4()的值,您可以传递不同类型的值。

如果您打算停止执行模板,则为模板注册的自定义函数应仅返回非string错误。因为如果您返回nil会发生什么。 template.FuncMap

  

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

工作示例

以下是使用您的模板和error函数的工作示例:

isIPv4()

输出(在Go Playground上尝试):

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

潜在错误

上述程序会输出以下错误:

传递无效的IP:

IPv4: 127.0.0.1

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

输出:

    "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,
})