loops - 如何将多个值从模板传递到模板?

标签 loops go struct slice go-templates

我的 City 结构是这样的:

type City struct {
    ID      int
    Name    string
    Regions []Region
}  

Region 结构是:

type Region struct {
    ID               int
    Name             string
    Shops            []Destination
    Masters          []Master
    EducationCenters []Destination
}

主要我尝试这样做:

tpl.ExecuteTemplate(resWriter,"cities.gohtml",CityWithSomeData)

是否可以在模板中做这样的事情?

{{range .}}
        {{$city:=.Name}}
            {{range .Regions}}
                      {{$region:=.Name}}
                      {{template "data" .Shops $city $region}}
            {{end}}
{{end}}

最佳答案

引自 text/template 的文档,{{template}} 操作的语法:

{{template "name"}}
    The template with the specified name is executed with nil data.

{{template "name" pipeline}}
    The template with the specified name is executed with dot set
    to the value of the pipeline.

这意味着您可以将一个可选数据传递给模板执行,而不是更多。如果你想传递多个值,你必须将它们包装成你传递的某个单一值。有关详细信息,请参阅 How to pass multiple data to Go template?

所以我们应该将这些数据包装到结构或映射中。但是我们不能在模板中编写 Go 代码。我们可以做的是注册一个我们将这些数据传递给的函数,该函数可以进行“打包”并返回一个值,现在我们可以将其传递给 {{template}} 操作。

这是一个示例包装器,它只是将这些包装到 map 中:

func Wrap(shops []Destination, cityName, regionName string) map[string]interface{} {
    return map[string]interface{}{
        "Shops":      shops,
        "CityName":   cityName,
        "RegionName": regionName,
    }
}

可以使用 Template.Funcs() 注册自定义函数方法,并且不要忘记在解析模板文本之前必须执行此操作。

这是一个修改后的模板,它调用此 Wrap() 函数来生成单个值:

const src = `
{{define "data"}}
    City: {{.CityName}}, Region: {{.RegionName}}, Shops: {{.Shops}}
{{end}}
{{- range . -}}
        {{$city:=.Name}}
        {{- range .Regions -}}
              {{$region:=.Name}}
              {{- template "data" (Wrap .Shops $city $region) -}}
        {{end}}
{{- end}}`

这是一个可运行的示例,展示了这些操作:

t := template.Must(template.New("cities.gohtml").Funcs(template.FuncMap{
    "Wrap": Wrap,
}).Parse(src))
CityWithSomeData := []City{
    {
        Name: "CityA",
        Regions: []Region{
            {Name: "CA-RA", Shops: []Destination{{"CA-RA-SA"}, {"CA-RA-SB"}}},
            {Name: "CA-RB", Shops: []Destination{{"CA-RB-SA"}, {"CA-RB-SB"}}},
        },
    },
    {
        Name: "CityB",
        Regions: []Region{
            {Name: "CB-RA", Shops: []Destination{{"CB-RA-SA"}, {"CB-RA-SB"}}},
            {Name: "CB-RB", Shops: []Destination{{"CB-RB-SA"}, {"CB-RB-SB"}}},
        },
    },
}
if err := t.ExecuteTemplate(os.Stdout, "cities.gohtml", CityWithSomeData); err != nil {
    panic(err)
}

输出(在 Go Playground 上尝试):

City: CityA, Region: CA-RA, Shops: [{CA-RA-SA} {CA-RA-SB}]

City: CityA, Region: CA-RB, Shops: [{CA-RB-SA} {CA-RB-SB}]

City: CityB, Region: CB-RA, Shops: [{CB-RA-SA} {CB-RA-SB}]

City: CityB, Region: CB-RB, Shops: [{CB-RB-SA} {CB-RB-SB}]

关于loops - 如何将多个值从模板传递到模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49473199/

相关文章:

gotk3,带有自定义小部件的笔记本附加页面并将其取回

c# - 存储在 c# 列表中的嵌套结构或类

JavaScript 属性最终会陷入循环

php - 如何避免在子数据循环内调用数据库查询

java - 向 foreach 循环添加额外的参数

go - 等待完成后我们是否需要创建新的 WaitGroup ?

json - 对嵌套结构使用自定义解码时,GoLang 结构无法正确解码

php - 遍历数组并删除重复项

go - "Golang is more productive because any type can be given methods"。这如何提高生产力?

GO:如何使用 redigo 将结构保存和检索到 redis