【问题标题】:Golang template and testing for Valid fieldsGolang 模板和有效字段的测试
【发布时间】:2018-07-04 04:11:41
【问题描述】:

在 Go 的 database/sql 包中,有一堆 Null[Type] 结构可以帮助将数据库值(及其可能的空值)映射到代码中。我试图弄清楚如何测试结构 field 是否为空,或者换句话说,它的 Valid 属性是否为假。

打印 SQL 字段的推荐方法是使用 .Value 属性,如下所示:

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

这很好用。

但是假设我有一些稍微复杂一点的东西,我需要根据其他东西来测试这个值,例如:

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

碰巧,这也很有效,除非 .MyField 不是有效的,在这种情况下我会收到错误,“错误调用 eq:用于比较的无效类型”。该错误是有道理的,因为 Go 无法将 nil 字段与另一个值(或类似的值)进行比较。

我原以为“简单”的解决方案是首先测试 Value 是否为 nil,然后将其与我需要的值进行比较,如下所示:

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

在这种情况下,我得到相同的“错误调用 eq:用于比较的类型无效”。我猜这意味着 .MyField “存在”,即使 .MyField 的值无效。所以,然后我尝试了六个其他版本,大部分都出现相同的错误,例如:

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

此时,我意识到我根本不明白如何测试有效字段的存在。如有任何帮助,我将不胜感激。

谢谢。

【问题讨论】:

    标签: templates if-statement go go-templates


    【解决方案1】:

    Go 模板中的 and 函数不是短路计算的(与 Go 中的 &amp;&amp; 运算符不同),它的所有参数总是被计算。引用自 text/template 包文档:

    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.
    

    这意味着您的{{if}} 操作:

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

    即使如果$.MyStruct.MyFieldnil,条件将被评估为false,但eq $.MyStruct.MyField.Value . 也会被评估并导致您得到错误。

    相反,您可以嵌入多个 {{if}} 操作,如下所示:

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

    您也可以使用{{with}} 操作,但这也会设置点,因此您必须小心:

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

    注意:

    您在问题中谈论的是nil 值,但sql.NullXX 类型是不能是nil 的结构。在这种情况下,您必须检查其Valid 字段以判断其Value() 方法是否会在调用时返回非nil 值。它可能看起来像这样:

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

    【讨论】:

    • 完美,谢谢 icza!我需要做的唯一小改动——我不知道为什么——是在第一个 if 条件中添加 .Valid,如下所示:{{ if $.MyStruct.MyField.Valid }} {{if eq $. MyStruct.MyField.Value .}}selected="selected"{{end}}{{end}}。有了这个,这个模板终于可以工作了。
    • @Brent 然后看起来您没有使用指向结构的指针,而是使用结构值。在您的问题中,您指的是nil 值,并且只有指针具有nil 值,而不是结构。请参阅编辑后的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2013-10-08
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多