为了账号安全,请及时绑定邮箱和手机立即绑定

golang中模板内的变量

golang中模板内的变量

Go
拉莫斯之舞 2021-11-15 15:40:50
html/text模板中变量的命名空间是什么?我认为变量$x可以改变模板内的值,但这个例子告诉我我不能。当我尝试按年份分组比赛时我失败了 - 像这样(http://play.golang.org/p/EX1Aut_ULD):package mainimport (    "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)    }}
查看完整描述

3 回答

?
繁花不似锦

TA贡献1851条经验 获得超4个赞

编辑:有关更新的答案,请参阅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)

    }

}



查看完整回答
反对 回复 2021-11-15
?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

在 go1.11 text/template 中,因此 html/template 变得能够设置现有变量的值,这意味着可以通过一个非常小的修改来使原始代码工作。

改变

{{$prev_year:=$year}}

{{$prev_year = $year}}


查看完整回答
反对 回复 2021-11-15
?
九州编程

TA贡献1785条经验 获得超4个赞

正如this answer所述,该变量“重新分配”的范围以{{end}}块结束。因此,仅使用标准变量无法解决问题,应该在执行模板的 Go 程序中解决。


然而,在某些框架中,这并不容易(例如 protoc-gen-gotemplate)。


该小枝库增加了额外的功能,以标准的模板语言。其中之一是可变映射,可以通过以下方式使用:


// init the dictionary (you can init it without initial key/values as well)

{{$myVar := dict "key" "value"}}


// getting the "key" from the dictionary (returns array) and then fetching the first element from that array

{{pluck "key" $myVar | first}}


// conditional update block

{{if eq "some" "some"}}

     // the $_ seems necessary because Go template functions need to return something

     {{$_ := set $myVar "key" "newValue"}}

{{end}}


// print out the updated value

{{pluck "key" $myVar | first}}

这个小例子打印出来:


value

newValue

一种实用的方法是对所有可变变量使用单个字典,并将它们作为键存储在相应的变量名下。


参考:


http://masterminds.github.io/sprig/dicts.html

https://github.com/Masterminds/sprig


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 251 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信