如何通过模板中的变量访问对象字段?

How do I access object field by variable in template?

我有一个嵌套循环:

{{$columns := .columns}}
{{range $dx := .dataList}}
    {{range $c := $columns}}
        {{index $dx $c}}
    {{end}}
{{end}}

dataList是orm模型数组。使用 ID, Title fields ,然后 columns[]string 变量包含所有 orm 模型字段名称,如 ID, Title.

type AdFile struct {
    ID      uint `gorm:"primary_key"`
    Title   string
}

我试过 {{(index .listData 0).Title}} 并且有效。

但是,如果我想访问 $dx.Title$dx.ID .... 使用 TitleID 作为变量,但它不起作用。我试过了 $dx[$c].

可以轻松实现与 Python 相同的事情

for i in list_data
    tr
        for p in columns
            td=i[p]

要访问由名称给定的结构的字段值,您需要 reflect 包的帮助。可以这样做:

v := AdFile{ID:1, Title: "T1"} // A struct value
name := "ID"                   // field name

fieldValue := reflect.ValueOf(v).FieldByName(name).Interface()

由于这是 Go 代码,您不能将其嵌入到模板中。但是您可以使用可以从模板调用的 Template.Funcs() 方法注册自定义函数。

所以让我们这样做:将此功能包装到一个函数中,并通过名称 "Field" 注册它,以便我们可以从我们的模板中调用它。

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "Field": func(v interface{}, name string) interface{} {
            return reflect.ValueOf(v).FieldByName(name).Interface()
        },
    }).Parse(templ))

    m := map[string]interface{}{
        "columns": []string{"ID", "Title"},
        "dataList": []AdFile{
            {ID: 1, Title: "Title1"},
            {ID: 2, Title: "Title2"},
        },
    }

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }

}

const templ = `{{$columns := .columns}}
{{range $dx := .dataList}}
    {{range $c := $columns}}
        {{- Field $dx $c }}
    {{end}}
{{end}}`

上述应用程序的输出(在 Go Playground 上尝试):

1
Title1


2
Title2

注意:注册的"Field"函数中省略了错误检查。如果给定的字段名称无效,您可以将其改进为 return nil,或者 return 由模板引擎处理的错误(在这种情况下,模板执行将因错误而中止你return).