给定一组结构,我如何使用“范围”模板迭代器打印出一个表,该表为每个结构分配一行,为每个字段值分配一列,而无需显式命名字段?
container := []Node type Node struct { Contact_id int Employer_id int First_name string Middle_name string Last_name string }
模板代码:
{{range .container}} <tr> <td>{{.Prefix}}</td> <td>{{.First_name}}</td> <td>{{.Middle_name}}</td> <td>{{.Last_name}}</td> <td>{{.Contact_id}}</td> <td>{{.Employer_id}}</td> </tr> {{end}}
当我尝试使用迭代值时
{{range .container}} {{range .}} <td>{{.}}</td> {{end}} {{end}}
有人告诉我,我无法遍历价值观。有什么干净的方法可以做到这一点吗?
使用html/template,您无法遍历结构中的字段。在该包的文档中,您可以阅读:
html/template
{{范围管道}} T1 {{end}} 管道的值必须是数组,切片,映射或通道。
也就是说,管道不能是结构。您需要:
[][]interface{}
由于结构是在编译时定义的,并且在运行时不会更改其结构,因此不需要迭代,也不会使模板中的内容更加清楚。我不建议这样做。
编辑
但是有时候反思是一件好事。布伦登还指出,您实际上可以让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} // In the template, we use rangeStruct to turn our struct values // into a slice we can iterate over 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"}, } // We create the template and register out template function 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) } } // RangeStructer takes the first argument, which must be a struct, and // returns the value of each field in a slice. It will return nil // if there are no arguments or first argument is not a struct 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>
操场