使用
html/template
,您无法迭代结构体中的字段。在
文档中,您可以阅读到:
{{range pipeline}} T1 {{end}}
管道的值必须是数组、切片、映射或通道。
也就是说,管道不能是结构体。要么您需要:
- 使用一个中间类型,例如
[][]interface{}
,作为容器变量传递给模板
- 像您展示的那样单独输入每个单元格
- 创建一个模板函数,将结构体值转换为您可以迭代的某种类型
由于结构体在编译时定义并且不会在运行时改变其结构,因此迭代是不必要的,而且在模板中不会使事情更清晰。我建议避免这样做。
编辑
但有时反射是一件好事。Brenden还指出,您实际上可以让range迭代从函数返回的值。如果使用反射,这将是最简单的方法。
使用模板函数的完整工作示例:
package main
import (
"html/template"
"os"
"reflect"
)
type Node struct {
Contact_id int
Employer_id int
First_name string
Middle_name string
Last_name string
}
var templateFuncs = template.FuncMap{"rangeStruct": RangeStructer}
var htmlTemplate = `{{range .}}<tr>
{{range rangeStruct .}} <td>{{.}}</td>
{{end}}</tr>
{{end}}`
func main() {
container := []Node{
{1, 12, "Accipiter", "ANisus", "Nisus"},
{2, 42, "Hello", "my", "World"},
}
t := template.New("t").Funcs(templateFuncs)
t, err := t.Parse(htmlTemplate)
if err != nil {
panic(err)
}
err = t.Execute(os.Stdout, container)
if err != nil {
panic(err)
}
}
func RangeStructer(args ...interface{}) []interface{} {
if len(args) == 0 {
return nil
}
v := reflect.ValueOf(args[0])
if v.Kind() != reflect.Struct {
return nil
}
out := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
out[i] = v.Field(i).Interface()
}
return out
}
输出:
<tr>
<td>1</td>
<td>12</td>
<td>Accipiter</td>
<td>ANisus</td>
<td>Nisus</td>
</tr>
<tr>
<td>2</td>
<td>42</td>
<td>Hello</td>
<td>my</td>
<td>World</td>
</tr>
Playground
.container.Nodes
是什么?如果你想要遍历container
,只需要使用.container
即可。 - nemo