Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Templates 在Go模板中按名称访问结构成员_Templates_Go_Go Templates - Fatal编程技术网

Templates 在Go模板中按名称访问结构成员

Templates 在Go模板中按名称访问结构成员,templates,go,go-templates,Templates,Go,Go Templates,我希望创建一个通用的Go html模板,它将根据输入生成一个标准的html表。我本来希望按名称查找struct成员,但一直未能成功 我环顾四周,找不到解决方案,所以我要么错过了一些明显的东西,要么方法错了。在这方面,我会接受一个解决方案,它显示了一种替代或更好的方法,可以避免尝试这种查找 模板示例: {{ $fields := .FieldMap }} <table> <thead> <tr> {{ range $key, $value

我希望创建一个通用的Go html模板,它将根据输入生成一个标准的html表。我本来希望按名称查找struct成员,但一直未能成功

我环顾四周,找不到解决方案,所以我要么错过了一些明显的东西,要么方法错了。在这方面,我会接受一个解决方案,它显示了一种替代或更好的方法,可以避免尝试这种查找

模板示例:

{{ $fields := .FieldMap }}
<table>
    <thead>
    <tr>
    {{ range $key, $value := $fields }}
        <th>{{ $key }}</th>
    {{ end }}
    </tr>

    </thead>
    <tbody>
    {{ range $i, $v :=  .Model }}
    <tr>
        {{ $rowData := . }}
{{/* FAILS: error calling index: can't index item of type main.Person  <td> {{ index . "FirstName"}}</td>*/}}
        {{ range $key, $value := $fields }}

{{/* FAILS: error calling index: can't index item of type main.Person   <td> {{ index $rowData $value }}</td>*/}}
{{/* FAILS: bad character U+0024 '$'                                    <td> {{ $rowData.$value }}</td>*/}}
        {{ end }}
    </tr>
    {{ end }}
    </tbody>
</table>

我希望我想做的事情很清楚-有一个单一的模板,我可以在各种类型的结构中重复使用。

创建一个模板函数,以映射形式返回结构字段名称和值:

// fields returns map of field names and values for struct s.
func fields(s interface{}) (map[string]interface{}, error) {
    v := reflect.Indirect(reflect.ValueOf(s))
    if v.Kind() != reflect.Struct {
        return nil, fmt.Errorf("%T is not a struct", s)
    }
    m := make(map[string]interface{})
    t := v.Type()
    for i := 0; i < t.NumField(); i++ {
        sv := t.Field(i)
        m[sv.Name] = v.Field(i).Interface()
    }
    return m, nil
}
像这样使用它:

{{range $i, $v :=  .Model}}
<tr>
    {{$m := fields $v}}
    {{range $key, $value := $fields}}
       <td>{{index $m $value}}</td>
    {{end}}
</tr>
{{end}}
{{range $i, $v :=  .Model}}
<tr>
    {{range $key, $value := $fields}}
       <td>{{field $v $value}}</td>
    {{end}}
</tr>
{{end}}
使用以下函数进行分析:

t, err := template.New("").Funcs(template.FuncMap{"field": field}).ParseFiles("table.gohtml")
像这样使用它:

{{range $i, $v :=  .Model}}
<tr>
    {{$m := fields $v}}
    {{range $key, $value := $fields}}
       <td>{{index $m $value}}</td>
    {{end}}
</tr>
{{end}}
{{range $i, $v :=  .Model}}
<tr>
    {{range $key, $value := $fields}}
       <td>{{field $v $value}}</td>
    {{end}}
</tr>
{{end}}
{{range$i,$v:=.Model}
{{range$key,$value:=$fields}
{{field$v$value}
{{end}
{{end}

.

你不能。如果要迭代模板中的键/值,请使用
map
,而不是
struct
。因此,您是否建议将该结构转换为类似map[string]接口的界面,其中键是成员名称?这确实是您的选择。就我个人而言,在我看来,你不太可能最终得到一个应用程序,在这个应用程序中,你使用同一个模板来呈现一堆不同的对象,只想以任意顺序列出它们的所有字段,而没有任何特殊的格式或行为。这听起来像是调试,我可能只会使用JSON或其他东西进行调试。因此,似乎只使用不同模板的结构是明智的长期解决方案。但这是你的项目,你比任何人都清楚,这是你的设计决定。谢谢-第二种方法是我需要的。在Go-gin框架中,您可以在路由器/引擎路由器处添加模板函数:=gin.Default()router.SetFuncMap(template.FuncMap{“field”:field,})
{{range $i, $v :=  .Model}}
<tr>
    {{range $key, $value := $fields}}
       <td>{{field $v $value}}</td>
    {{end}}
</tr>
{{end}}