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

如何在Golang模板中的嵌套范围内引用作用域中更高的struct元素?

示例:

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}}

明显地wine 吧和..我不工作,但希望我的意图是明确的.我想遍历Foo和Bar的所有组合,并生成一个表单元素,其名称由Foo的Id和Bar的Id生成.

问题是,似乎不可能:

  1. 从foos范围范围内的访问栏
  2. 从栏的范围范围内访问foo的ID

我通过在两个 struct 中都放了一堆多余的字段来临时解决这个问题,但是在我看来这非常难看,违反了Dry,而且通常感觉非常不对劲.

golang模板有什么方法可以实现我想做的吗?

推荐答案

是.我觉得not找到解决方案似乎是因为没有仔细阅读text/template包.如果您使用的是html/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())
}

注意:您可能可以不将文件加载到中间缓冲区(使用ParseFiles),我只是复制并粘贴了一些为我的一个项目编写的代码.

模板文件:

{{ $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}}

这个故事的两个寓意是
a)明智地使用模板中的变量,它们是有益的
b)在模板范围内还可以设置变量,不需要只依赖$.

Go相关问答推荐

有没有更简单的方法在Go中编写这个逻辑?

如何从google.golang.org/grpc/stats包中将golang中不同事件的输出进行组合,以获取func HandlePRC

无法在Macos上使用Azure Speech golang SDK

Go中的Slice[:1][0]与Slice[0]

如何从 nil 指针创建值

Cypher 查找(多个)最低 node

这是go语言gin提供的关于TypeEngine和RouterGroup的问题

使用 Golang 获取目录磁盘使用情况

Golang 发送Post请求出现400错误

从 eBPF LRU 哈希映射中错误驱逐的元素

具有嵌套重复的正则表达式

Golang:如何判断通过缓冲通道进行通信时生产者或消费者是否较慢?

Go 泛型:自引用接口约束

Go AST:获取所有 struct

分配空切片而不引用其类型?

具有相同提前返回语句的函数的不同基准测试结果

如何使用通用字段初始化匿名struct数组

Go 泛型是否与 LINQ to Objects 等效?

将函数的值作为输入参数返回给另一个

如何访问 Go 模板中数组的第一个索引的值