ではhtml/template
、構造体のフィールドを反復処理できません。パッケージのドキュメントでは、次を読むことができます。
{{range パイプライン}} 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}
// 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>
遊び場