Templates Go模板:是否可以嵌套范围?

Templates Go模板:是否可以嵌套范围?,templates,go,Templates,Go,这个看起来很简单,但它让我发疯 如何在golang模板的嵌套范围内引用范围中较高的结构元素 例如: type Foo struct { Id string Name string } type Bar struct { Id string Name string } var foos []Foo var bars []Bar // logic to populate both foos and bars 在模板中: {{range .foos}} <div>

这个看起来很简单,但它让我发疯

如何在golang模板的嵌套范围内引用范围中较高的结构元素

例如:

type Foo struct {
  Id string
  Name string
}

type Bar struct {
  Id string
  Name string
}

var foos []Foo
var bars []Bar

// logic to populate both foos and bars
在模板中:

{{range .foos}}
  <div>Foo {{.Name}}</div>
  <div>
    {{range ..bars}}
      <div>Bar {{.Name}} <input type="text" name="ids_{{..Id}}_{{.Id}}" /></div>
    {{end}}
  </div>
{{end}}
{{range.foos}
Foo{{.Name}
{{range..bar}
条{{.Name}
{{end}
{{end}
显然…酒吧和…我不工作,但希望我的意图是明确的。我希望遍历Foo和Bar的所有组合,并生成一个表单元素,其名称由Foo的Id和Bar的Id生成

问题在于,似乎不可能:

  • 从foos范围内的访问栏
  • 从酒吧的范围内访问Foo的Id
  • 我有一个临时的解决办法,在两个结构中都放了一堆冗余字段,但这对我来说非常难看,而且总体上感觉非常错误

    golang模板有什么方法可以完成我想做的事情吗?

    有。我觉得没有找到解决方案似乎是因为没有仔细阅读
    文本/模板
    包。如果您使用的是
    html/template
    ,语法是相同的(它们告诉您阅读text/template;)。下面是一个完整的工作解决方案,可以解决您可能想要做的事情

    Go文件:

    package main
    
    import (
        "bytes"
        "io/ioutil"
        "os"
        "strconv"
        "text/template"
    )
    
    type Foo struct {
        Id   string
        Name string
    }
    
    type Bar struct {
        Id   string
        Name string
    }
    
    var foos []Foo
    var bars []Bar
    
    func main() {
        foos = make([]Foo, 10)
        bars = make([]Bar, 10)
    
        for i := 0; i < 10; i++ {
            foos[i] = Foo{strconv.Itoa(i), strconv.Itoa(i)} // just random strings
            bars[i] = Bar{strconv.Itoa(10 * i), strconv.Itoa(10 * i)}
        }
    
        tmpl, err := ioutil.ReadFile("so.tmpl")
        if err != nil {
            panic(err)
        }
    
        buffer := bytes.NewBuffer(make([]byte, 0, len(tmpl)))
    
        output := template.Must(template.New("FUBAR").Parse(string(tmpl)))
        output.Execute(buffer, struct {
            FooSlice []Foo
            BarSlice []Bar
        }{
            FooSlice: foos,
            BarSlice: bars,
        })
    
        outfile, err := os.Create("output.html")
        if err != nil {
            panic(err)
        }
        defer outfile.Close()
        outfile.Write(buffer.Bytes())
    }
    
    这个故事的两个寓意是
    a) 明智地使用模板中的变量,它们是有益的
    b) 模板中的范围也可以设置变量,您不需要仅依赖
    $

    {{ $foos := .FooSlice }}
    {{ $bars := .BarSlice }}
    
    {{range $foo := $foos }}
      <div>Foo {{$foo.Name}}</div>
      <div>
        {{range $bar := $bars}}
          <div>Bar {{$bar.Name}} <input type="text" name="ids_{{$foo.Id}}_{{$bar.Id}}" /></div>
        {{end}}
      </div>
    {{end}}