douzhan1238 2018-07-04 04:11
浏览 52
已采纳

Golang模板并测试有效字段

In Go's database/sql package, there are a bunch of Null[Type] structs that help map database values (and their possible nulls) into code. I'm trying to figure out how to test whether a struct field is null, or in other words, when its Valid property is false.

The recommended way to print a SQL field is to use the .Value property, like this:

<div>{{ .MyStruct.MyField.Value }}</div>

This works great.

But suppose I have something slightly more complicated, where I need to test the value against something else, for example:

<select name="y">
   {{ range .SomeSlice }}
       <option value="{{ . }}" {{ if eq $.MyStruct.MyField.Value .}}selected="selected"{{ end }}>{{ . }}</option>
   {{ end }}
</select>

As it happens, this works great, too, unless .MyField is not Valid, in which case I get the error, "error calling eq: invalid type for comparison". The error makes sense, because Go can't compare a nil Field against another value (or something like that).

I would have thought the 'easy' solution would be to test first whether the Value is nil, and then compare it against what I need, like this:

<select name="y">
   {{ range .SomeSlice }}
       <option value="{{ . }}" {{ if and ($.MyStruct.MyField) (eq $.MyStruct.MyField.Value .)}}selected="selected"{{ end }}>{{ . }}</option>
   {{ end }}
</select>

In this case, I get the same "error calling eq: invalid type for comparison". I guess that means .MyField "exists" even though the value of .MyField is not Valid. So, then I tried a half dozen other versions, mostly with the same error, for example:

<select name="y">
   {{ range .SomeSlice }}
       <option value="{{ . }}" {{ if and ($.MyStruct.MyField.Valid) (eq $.MyStruct.MyField.Value .)}}selected="selected"{{ end }}>{{ . }}</option>
   {{ end }}
</select>

At this point, I'm realizing I really don't understand how to test for the existence of a valid field at all. I'd appreciate any help you might have.

Thanks.

  • 写回答

1条回答 默认 最新

  • douchanxiu5636 2018-07-04 06:51
    关注

    The and function in Go templates is not short-circuit evaluated (unlike the && operator in Go), all its arguments are evaluated always. Quoting from text/template package doc:

    and
        Returns the boolean AND of its arguments by returning the
        first empty argument or the last argument, that is,
        "and x y" behaves as "if x then y else x". All the
        arguments are evaluated.
    

    This means that the {{if}} action of yours:

    {{ if and ($.MyStruct.MyField) (eq $.MyStruct.MyField.Value .)}}
    

    Even though the condition would be evaluated to false if $.MyStruct.MyField is nil, but eq $.MyStruct.MyField.Value . will also be evaluated and result in the error you get.

    Instead you may embed multiple {{if}} actions, like this:

    {{if $.MyStruct.MyField}}
        {{if eq $.MyStruct.MyField.Value .}}selected="selected"{{end}}
    {{end}}
    

    You may also use the {{with}} action, but that also sets the dot, so you have to be careful:

    <select name="y">
       {{range $idx, $e := .SomeSlice}}
           <option value="{{.}}" {{with $.MyStruct.MyField}}
                   {{if eq .Value $e}}selected="selected"{{end}}
               {{end}}>{{.}}</option>
       {{end}}
    </select>
    

    Note:

    You were talking about nil values in your question, but the sql.NullXX types are structs which cannot be nil. In which case you have to check its Valid field to tell if its Value() method will return you a non-nil value when called. It could look like this:

    {{if $.MyStruct.MyField.Valid}}
        {{if eq $.MyStruct.MyField.Value .}}selected="selected"{{end}}
    {{end}}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率