4

使用text/template,我需要找出数组中的任何对象是否具有特定的属性值。

假设我有一个人员列表(json):

[
    {"name": "ANisus", "sex":"M"},
    {"name": "Sofia", "sex":"F"},
    {"name": "Anna", "sex":"F"}
]

使用模板,我想要这个输出:

Females:
Sofia
Anna

但是标题,Females:,应该只显示在实际上有任何人sex设置为的情况下F。如何在模板系统中执行此操作?我的第一次尝试是使用变量:

{{$hasFemale := 0}}
{{range .}}{{if eq .sex "F"}}{{$hasFemale := 1}}{{end}}{{end}}
{{if $hasFemale}}Female:{{end}}

我没有让它工作,因为该范围内的 $hasFemale 处于不同的范围内,并且与以 0 启动的范围不同。一旦启动,我似乎无法找到更改变量的方法。

“工作”示例:http ://play.golang.org/p/T-Ekx7n9YQ

而且我无法将此逻辑移至应用程序;它必须在模板内完成。

4

2 回答 2

4

我会以不同的方式解决这个问题。您通常不需要模板中的状态,它们应该很简单。

由于您只想知道数据集中是否有女性,请在数据上定义一个方法HasFemales并从模板中调用它。您不一定需要定义结构,您可以使用自定义类型和这样的定义(您在 play 上修改的示例):

type People []interface{}

func (p People) HasFemale() bool {
    for _, v := range p {
        if m, ok := v.(map[string]interface{}); !ok {
            return false
        } else if _, ok := m["sex"]; ok && m["sex"] == "F" {
            return true
        }
    }
    return false
}

您的模板将如下所示:

{{if .HasFemale}}Female:
    {{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}}
{{end}}

当然,这不像结构那样类型安全,也不像结构那么好,所以我建议使用encoding/json反射功能将值映射到结构并在其上定义方法。这还具有能够在.HasFemale内部缓存结果的好处,因此您不需要每次都进行迭代。

关于您的评论的更新

我的 Go 应用程序有两个参数:1)一个模板文件和 2)一个 json 文件。它使用数据执行模板并输出文件。然后将输出文件传递给 wkhtmltopdf 以生成 pdf。每个模板/数据对都有我无法控制的任意数据结构,因此 Go 应用程序必须是通用的

在这种情况下,使HasFemale通用。这与您在问题中所做的类似,但有利于抽象范围的嵌套,使您可以将结果存储在变量中并在整个模板中拥有状态。例子:

type Data []interface{}

func (p Data) HasField(name string, value interface{}) bool {
    for _, v := range p {
        if m, ok := v.(map[string]interface{}); !ok {
            return false
        } else if _, ok := m[name]; ok && reflect.DeepEqual(m[name], value) {
            return true
        }
    }
    return false
}

示例用法:

{{$hasFemale := .HasField "sex" "F"}}
{{if $hasFemale}}Female:
    {{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}}
{{end}}`
于 2013-10-10T11:01:49.320 回答
1

我知道这是一个老问题,但是我只是有一个类似的用例,我需要根据字段是否存在于范围内的任何位置来使 html 表中的列可选。

原始海报几乎就在那里,他们只是经常遇到 go 问题,并且将变量设置在错误的范围内。

因此,{{$hasFemale := 1}}与其在 if 中设置变量,不如将其编写为{{$hasFemale = 1}}then 它会像他们最初编写的那样工作。

{{$hasFemale := 0}}
{{range .}}{{if eq .sex "F"}}{{$hasFemale = 1}}{{end}}{{end}}
{{if $hasFemale}}Female:{{end}}

这是他们修复https://play.golang.org/p/m_RPJmqsuet的原始示例

于 2021-09-08T06:32:41.197 回答