22

html/textテンプレート内の変数の名前空間とは? 変数はテンプレート内の値を変更できると思っていました$xが、この例ではできないことがわかりました。

年ごとにトーナメントをグループ化しようとしたときに失敗しました-次のようなものです(http://play.golang.org/p/EX1Aut_ULD):

package main

import (
    "fmt"
    "os"
    "text/template"
    "time"
)

func main() {
    tournaments := []struct {
        Place string
        Date  time.Time
    }{
        // for clarity - date is sorted, we don't need sort it again
        {"Town1", time.Date(2015, time.November, 10, 23, 0, 0, 0, time.Local)},
        {"Town2", time.Date(2015, time.October, 10, 23, 0, 0, 0, time.Local)},
        {"Town3", time.Date(2014, time.November, 10, 23, 0, 0, 0, time.Local)},
    }
    t, err := template.New("").Parse(`
{{$prev_year:=0}}
{{range .}}
    {{with .Date}}
        {{$year:=.Year}}
                    {{if ne $year $prev_year}}
                        Actions in year {{$year}}:
                {{$prev_year:=$year}}
            {{end}}
    {{end}}

        {{.Place}}, {{.Date}}
    {{end}}

    `)
    if err != nil {
        panic(err)
    }
    err = t.Execute(os.Stdout, tournaments)
    if err != nil {
        fmt.Println("executing template:", err)
    }
}
4

3 に答える 3

18

go1.11ではtext/template 、ひいては html/template で既存の変数の値を設定できるようになりました。

変化する

{{$prev_year:=$year}}

{{$prev_year = $year}}

遊び場

于 2018-10-22T09:07:11.493 に答える
17

編集:最新の回答については、https ://stackoverflow.com/a/52925780/1685538 を参照してください。


元の答え:

https://golang.org/pkg/text/template/#hdr-Variables :

変数のスコープは、変数が宣言されている制御構造 (「if」、「with」、または「range」) の「終了」アクションまで、またはそのような制御構造がない場合はテンプレートの最後まで拡張されます。

したがって、次の行まで生きているだけで$prev_year定義します( )。{{$prev_year:=$year}}{{end}}

それを回避する方法はないようです。

これを行う「正しい」方法は、そのロジックをテンプレートから取り除き、Go コードでグループ化を行うことです。

これが実際の例です: https://play.golang.org/p/DZoSXo9WQR

package main

import (
    "fmt"
    "os"
    "text/template"
    "time"
)

type Tournament struct {
    Place string
    Date  time.Time
}

type TournamentGroup struct {
    Year        int
    Tournaments []Tournament
}

func groupTournamentsByYear(tournaments []Tournament) []TournamentGroup {
    if len(tournaments) == 0 {
        return nil
    }

    result := []TournamentGroup{
        {
            Year:        tournaments[0].Date.Year(),
            Tournaments: make([]Tournament, 0, 1),
        },
    }

    i := 0
    for _, tournament := range tournaments {
        year := tournament.Date.Year()
        if result[i].Year == year {
            // Add to existing group
            result[i].Tournaments = append(result[i].Tournaments, tournament)
        } else {
            // New group
            result = append(result, TournamentGroup{
                Year: year,
                Tournaments: []Tournament{
                    tournament,
                },
            })
            i++
        }
    }

    return result
}

func main() {
    tournaments := []Tournament{
        // for clarity - date is sorted, we don't need sort it again
        {"Town1", time.Date(2015, time.November, 10, 23, 0, 0, 0, time.Local)},
        {"Town2", time.Date(2015, time.October, 10, 23, 0, 0, 0, time.Local)},
        {"Town3", time.Date(2014, time.November, 10, 23, 0, 0, 0, time.Local)},
    }

    t, err := template.New("").Parse(`
{{$prev_year:=0}}
{{range .}}
    Actions in year {{.Year}}:
    {{range .Tournaments}}

            {{.Place}}, {{.Date}}
    {{end}}
    {{end}}

    `)
    if err != nil {
        panic(err)
    }
    err = t.Execute(os.Stdout, groupTournamentsByYear(tournaments))
    if err != nil {
        fmt.Println("executing template:", err)
    }
}
于 2015-10-09T11:25:16.910 に答える