How to have short circuit with and/or in text/template

huangapple go评论83阅读模式
英文:

How to have short circuit with and/or in text/template

问题

我有这个Go模板:

{{ if and $b.Trigger $b.Trigger.Name }} 
  Name is {{ $b.Trigger.Name }}.
{{ else }}
  ...其他内容...
{{ end }}

我试图让这个模板实现以下功能:

if b.Trigger != nil && $b.Trigger.Name != "" { ...

然而它不起作用,因为根据text/template godoc所说,and/or函数的两个参数都会被求值。

当求值$b.Trigger.Name时,它会出错,因为$b.Trigger可能为nil。所以它返回错误:

template: builds.html:24:46: 执行“content”时出错,位于<$b.Trigger.Name>:无法在类型*myType中评估字段Name

我尝试重构为:

{{ if and (ne $b.Trigger nil) (ne $b.Trigger.Name "") }}

但奇怪的是,这也失败了,它说我不能将$b.Trigger与nil进行比较,这是没有意义的,因为该字段是一个指针类型:

template: builds.html:24:31: 执行“content”时出错,位于<ne $b.Trigger nil>:调用ne时出错:比较的类型无效

有什么想法吗?

英文:

I have this Go template:

{{ if and $b.Trigger $b.Trigger.Name }} 
  Name is {{ $b.Trigger.Name }}.
{{ else }}
  ...other stuff...
{{ end }}

I'm trying to get this template to do:

if b.Trigger != nil &amp;&amp; $b.Trigger.Name != &quot;&quot; { ...

however it doesn't work, because as text/template godoc says, both arguments to and/or functions are evaluated.

When the $b.Trigger.Name is evaluated, it errors out because $b.Trigger can be nil. So it returns error:

> template: builds.html:24:46: executing &quot;content&quot; at &lt;$b.Trigger.Name&gt;: can&#39;t evaluate field Name in type *myType

I tried refactoring this to:

{{ if and (ne $b.Trigger nil) (ne $b.Trigger.Name &quot;&quot;) }}

and weird enough, this fails as well, it says I can't compare $b.Trigger with nil, which doesn't make sense because that field is a pointer type:

> template: builds.html:24:31: executing &quot;content&quot; at &lt;ne $b.Trigger nil&gt;: error calling ne: invalid type for comparison

Any ideas?

答案1

得分: 5

如Volker在上面提到的,嵌套if语句:

{{if $b.Trigger}}{{if $b.Trigger.Name}}
  名称是{{ $b.Trigger.Name }}。
{{end}}{{end}}

或者更简洁地:

{{with $b.Trigger}}{{with .Name}}
  名称是{{.}}。
{{end}}{{end}}

不幸的是,上述方法无法处理else子句。下面是一个(相当丑陋的)可能性:

{{$bTriggerName := ""}}
{{with $b.Trigger}}{{$bTriggerName = .Name}}{{end}}
{{with $bTriggerName}}
  名称是{{.}}。
{{else}}
  ...其他内容...
{{end}}

我查看了gobuffalo/plush是否可以更优雅地实现这一点,但截至2019-04-30,它无法做到。

英文:

As Volker noted above, nest the ifs:

{{if $b.Trigger}}{{if $b.Trigger.Name}}
  Name is {{ $b.Trigger.Name }}.
{{end}}{{end}}

Or, more succinctly:

{{with $b.Trigger}}{{with .Name}}
  Name is {{.}}.
{{end}}{{end}}

Unfortunately, the above won't handle else clauses. Here's one (rather ugly) possibility:

{{$bTriggerName := &quot;&quot;}}
{{with $b.Trigger}}{{$bTriggerName = .Name}}{{end}}
{{with $bTriggerName}}
  Name is {{.}}.
{{else}}
  ...other stuff...
{{end}}

I looked to see if gobuffalo/plush could do this more elegantly, but as of 2019-04-30 it cannot.

答案2

得分: 0

这里解释了为什么在管道中会评估所有的参数。它是通过Go模板函数进行评估的。
https://golang.org/pkg/text/template/#hdr-Functions

英文:

Here explains why all arguments are evaluated in a pipeline.
It is evaluated through go template functions
https://golang.org/pkg/text/template/#hdr-Functions

huangapple
  • 本文由 发表于 2017年6月16日 14:39:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/44582435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定