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

我可以从嵌套模板访问顶级模板变量吗?

我可以从嵌套模板访问顶级模板变量吗?

Go
交互式爱情 2023-08-14 17:34:11
假设我有一个带有这样的嵌套子模板的模板。游乐场链接package mainimport (    "os"    "text/template")type Person struct {    FirstName  string    SecondName string}type Document struct {    DocName string    People  []Person}const document = `Document name: {{.DocName}}{{range $person:=.People}}{{template "person" $person}}{{end}}{{- define "person"}}Person name is: {{.FirstName}} {{.SecondName}}{{end}}`func main() {    d := Document{        DocName: "first try",        People: []Person{            {"Brian", "Kernighan"},            {"Dennis", "Ritchie"},        },    }    t := template.Must(template.New("document").Parse(document))    err := t.Execute(os.Stdout, d)    if err != nil {        panic(err)    }}package mainimport (    "os"    "text/template")type Person struct {    FirstName  string    SecondName string}type Document struct {    DocName string    People  []Person}const document = `Document name: {{.DocName}}{{range $person:=.People}}{{template "person" $person}}{{end}}{{- define "person"}}Person name is: {{.FirstName}} {{.SecondName}}{{end}}`func main() {    d := Document{        DocName: "first try",        People: []Person{            {"Brian", "Kernighan"},            {"Dennis", "Ritchie"},        },    }    t := template.Must(template.New("document").Parse(document))    err := t.Execute(os.Stdout, d)    if err != nil {        panic(err)    }}type Person struct {    FirstName  string    SecondName string}type Document struct {    DocName string    People  []Person    SwitchNameOrder bool}const document = `Document name: {{.DocName}}{{range $person:=.People}}{{template "person" $person}}{{end}}{{- define "person"}}{{if $.SwitchNameOrder}} // <---- panic herePerson name is: {{.SecondName}} {{.FirstName}}{{else}}Person name is: {{.FirstName}} {{.SecondName}}{{end}}{{end}}`怎么做?是否可以?
查看完整描述

3 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

您可以做的一件事是使用模板函数将传递到子模板的变量与父模板中的变量“合并”。


type Person struct {

    FirstName  string

    SecondName string

}


type Document struct {

    DocName string

    People  []Person


    SwitchNameOrder bool

}


func personWithDocument(p Person, d Document) interface{} {

    return struct {

        Person

        Document Document

    }{p, d}

}


t := template.Must(template.New("document").Funcs(template.FuncMap{

    "personWithDocument": personWithDocument,

}).Parse(document))

然后在模板中您将执行以下操作:


const document = `

Document name: {{.DocName}}


{{range $person:=.People}}

{{template "person" (personWithDocument $person $) }}

{{end}}


{{- define "person"}}

{{if .Document.SwitchNameOrder}}

Person name is: {{.SecondName}} {{.FirstName}}

{{else}}

Person name is: {{.FirstName}} {{.SecondName}}

{{end}}

{{end}}

`

https://play.golang.org/p/YorPsMdr9g_H


查看完整回答
反对 回复 2023-08-14
?
收到一只叮咚

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

对于上述复杂的解决方案,更好的解决方案是停止尝试使用顶级配置选项,而是将其编写为模板函数,并将配置变量放在函数闭包中


{{- define "person"}}

{{if SwitchNameOrder}}

Person name is: {{.SecondName}} {{.FirstName}}

{{else}}

Person name is: {{.FirstName}} {{.SecondName}}

{{end}}

{{end}}


t := template.Must(template.New("document").Funcs(template.FuncMap{

    "SwitchNameOrder": func() bool {

        return switchNames // variable sits in closure

    },

}).Parse(document))

https://play.golang.org/p/O6QHtmxweOi


另一种选择是将整个切换编写为字符串函数,即:


{{- define "person"}}

Person name is: {{SwitchNames .FirstName .SecondName}}

{{end}}

并SwitchNames作为字符串函数


...Funcs(template.FuncMap{

    "SwitchNames": func(first, second string) string {

        if switchNames {

            return second + " " + first

        }

        return first + " " + second

    },

})...

可以更干净或更干净,具体取决于实际的复杂性


https://play.golang.org/p/UPB3NIpzw0N


查看完整回答
反对 回复 2023-08-14
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

我最终做的是添加一个单独的结构配置并将其复制到各处。那是,


type Config struct {

    SwitchNameOrder bool

}


type Person struct {

    FirstName  string

    SecondName string


    Config Config 

    // this could also be a pointer,

    // but I don't want to deal with nils, so let's copy

}


type Document struct {

    DocName string

    People  []Person


    Config Config

}


c := Config{SwitchNameOrder: true}


d.Config = c

for _, p := range d.People {

    p.Config = c

}

然后在模板中使用它



{{- define "person"}}

{{if .Config.SwitchNameOrder}}

Person name is: {{.SecondName}} {{.FirstName}}

{{else}}

Person name is: {{.FirstName}} {{.SecondName}}

{{end}}

{{end}}

很丑,但是该怎么办


https://play.golang.org/p/f95i4me8XLP


查看完整回答
反对 回复 2023-08-14
  • 3 回答
  • 0 关注
  • 94 浏览
慕课专栏
更多

添加回答

举报

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