私はこれを別の方法で解決します。通常、テンプレートに状態は必要ありません。テンプレートは単純であるべきです。
データセットに女性がいるかどうかだけを知りたいので、データにメソッドHasFemales
を定義し、テンプレートから呼び出します。必ずしも構造体を定義する必要はありません。カスタム型と次のような定義を使用できます (変更された例 on play ):
type People []interface{}
func (p People) HasFemale() bool {
for _, v := range p {
if m, ok := v.(map[string]interface{}); !ok {
return false
} else if _, ok := m["sex"]; ok && m["sex"] == "F" {
return true
}
}
return false
}
テンプレートは次のようになります。
{{if .HasFemale}}Female:
{{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}}
{{end}}
もちろん、これは構造体ほどタイプ セーフではなく、構造体ほど優れているわけでもないため、encoding/json
リフレクション機能を使用して値を構造体にマップし、その上でメソッドを定義することをお勧めします。これには、結果を内部的にキャッシュできるという利点もあるため、.HasFemale
毎回反復する必要はありません。
あなたのコメントに関する更新:
1) テンプレート ファイルと 2) json ファイルの 2 つの引数を取る Go アプリケーションがあります。データを使用してテンプレートを実行し、ファイルを出力します。次に、出力ファイルが wkhtmltopdf に渡され、pdf が生成されます。各テンプレート/データのペアは、私の制御を超えた任意のデータ構造を持っているため、Go アプリケーションは汎用的でなければなりません
この場合はHasFemale
ジェネリックにします。これは質問で行ったことと似ていますが、範囲のネストを抽象化する利点があり、結果を変数に格納してテンプレート全体に状態を保持できます。例:
type Data []interface{}
func (p Data) HasField(name string, value interface{}) bool {
for _, v := range p {
if m, ok := v.(map[string]interface{}); !ok {
return false
} else if _, ok := m[name]; ok && reflect.DeepEqual(m[name], value) {
return true
}
}
return false
}
使用例:
{{$hasFemale := .HasField "sex" "F"}}
{{if $hasFemale}}Female:
{{range .}}{{if eq .sex "F"}}{{.name}}{{end}}{{end}}
{{end}}`