1 回答
TA贡献1806条经验 获得超5个赞
我会以不同的方式解决这个问题。您通常不需要模板中的状态,它们应该很简单。
由于您只想知道您的数据集中是否有女性,因此请在您的数据上定义一个方法HasFemales并从模板中调用它。您不一定需要定义结构,您可以使用自定义类型和这样的定义(您修改后的示例):
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}}`
- 1 回答
- 0 关注
- 191 浏览
添加回答
举报