2013-07-07 8 views
12

これは一見シンプルですが、それは私を狂ってしまいます。Goテンプレート:ネストされた範囲は可能ですか?

golangテンプレートのネストされた範囲内のスコープ内の構造体要素をより高いレベルで参照するにはどうすればよいですか?

例:テンプレートで

type Foo struct { 
    Id string 
    Name string 
} 

type Bar struct { 
    Id string 
    Name string 
} 

var foos []Foo 
var bars []Bar 

// logic to populate both foos and bars 

{{range .foos}} 
    <div>Foo {{.Name}}</div> 
    <div> 
    {{range ..bars}} 
     <div>Bar {{.Name}} <input type="text" name="ids_{{..Id}}_{{.Id}}" /></div> 
    {{end}} 
    </div> 
{{end}} 

は明らか..barsと..Idは動作しませんが、うまくいけば、私の意図は明らかです。私はFooとBarのすべての組み合わせを繰り返し、FooのIdとBarのIdの両方によってビルドされた名前のフォーム要素を生成したいと思います。

問題は、それが不可能であるようだということです。FOOSの範囲内から

  1. アクセスバーバーの範囲の範囲内からのスコープに
  2. アクセスはFooのIDの範囲

私は両方の構造体に冗長フィールドの束を入れてこれに一時的な回避策がありますが、これは私には非常に醜いと思われ、DRYに違反し、一般的に非常に間違って感じます。

私がしたいことを行うためにgolangテンプレートを使用する方法はありますか?

答えて

17

はい。私はではないと感じる解決策を見つけることは、text/templateパッケージをよく読んでいないことから来ます。 html/templateを使用している場合、構文は同じです(テキスト/テン​​プレートを読むよう指示します)))。ここでは、あなたがやりたいことができる完全な実用的な解決策があります。

ゴーファイル:

package main 

import (
    "bytes" 
    "io/ioutil" 
    "os" 
    "strconv" 
    "text/template" 
) 

type Foo struct { 
    Id string 
    Name string 
} 

type Bar struct { 
    Id string 
    Name string 
} 

var foos []Foo 
var bars []Bar 

func main() { 
    foos = make([]Foo, 10) 
    bars = make([]Bar, 10) 

    for i := 0; i < 10; i++ { 
     foos[i] = Foo{strconv.Itoa(i), strconv.Itoa(i)} // just random strings 
     bars[i] = Bar{strconv.Itoa(10 * i), strconv.Itoa(10 * i)} 
    } 

    tmpl, err := ioutil.ReadFile("so.tmpl") 
    if err != nil { 
     panic(err) 
    } 

    buffer := bytes.NewBuffer(make([]byte, 0, len(tmpl))) 

    output := template.Must(template.New("FUBAR").Parse(string(tmpl))) 
    output.Execute(buffer, struct { 
     FooSlice []Foo 
     BarSlice []Bar 
    }{ 
     FooSlice: foos, 
     BarSlice: bars, 
    }) 

    outfile, err := os.Create("output.html") 
    if err != nil { 
     panic(err) 
    } 
    defer outfile.Close() 
    outfile.Write(buffer.Bytes()) 
} 

注:中間バッファ(ParseFilesを使用)にファイルをロードしないように何かをあなたはおそらく、私はちょうどコピーして、私は私の1のために書かれていたいくつかのコードを貼り付けることができますがプロジェクト。

テンプレートファイル:

{{ $foos := .FooSlice }} 
{{ $bars := .BarSlice }} 

{{range $foo := $foos }} 
    <div>Foo {{$foo.Name}}</div> 
    <div> 
    {{range $bar := $bars}} 
     <div>Bar {{$bar.Name}} <input type="text" name="ids_{{$foo.Id}}_{{$bar.Id}}" /></div> 
    {{end}} 
    </div> 
{{end}} 

慎重テンプレートで変数を使用するこの物語の2人のモラルが
a)に、彼らは
B有益されている)も、テンプレートの範囲で変数を設定することができ、あなたは必要ありません。 $または.

+0

ありがとう、このアプローチは素晴らしい作品です。 – haploid

関連する問題