我正在尝试定义在模板条件中使用的自定义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 }
在执行模板时,我没有任何错误,但是在尝试评估 {{如果IsIPv4 时,执行似乎停止了 。 }} 。
当然,在尝试解析和执行模板之前先对函数进行映射。
funcMap := template.FuncMap{ "IsIPv4": isIPv4, }
我刚接触Go,可能已经错过了一些东西(也许很明显?)。
为了进行一点调试,我尝试删除模板中的IsIPv4调用,并给出类似 {{if 的条件 。 }} 。结果是始终输出 IPv4:[IP地址] 。这对我来说很有意义。
我还查看了诸如 eq 之类的预定义Go功能,看来我正在尝试重现相同的想法,但没有成功。
TL; DR; 您必须检查error返回的值,template.Execute()或者template.ExecuteTemplate()它将告诉您为什么它不适合您。
error
template.Execute()
template.ExecuteTemplate()
首先,执行不会惊慌,因为它只会返回错误。您检查一下,您可能会立即知道出了什么问题:
if err := t.Execute(os.Stdout, data); err != nil { panic(err) }
接下来可能出问题的原因:您必须 在 解析模板 之前 注册自定义函数,因为模板引擎需要能够静态分析模板,并且它需要事先知道这IsIPv4是一个函数名:
IsIPv4
t := template.Must(template.New("").Funcs(template.FuncMap{ "IsIPv4": isIPv4, }).Parse(templ))
另一个潜在的错误是isIPv4()期望类型为的值string,并且您可能会传递不同类型的值。
isIPv4()
string
nil如果您打算停止执行模板,则为模板注册的自定义功能应仅返回非错误。因为这是如果您返回的情况error。template.FuncMap:
nil
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