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

假设我有一个带有这样的嵌套子模板的模板。游乐场链接

package main


import (

    "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 main


import (

    "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 here

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

{{else}}

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

{{end}}

{{end}}

`

怎么做?是否可以?


交互式爱情
浏览 96回答 3
3回答

阿晨1998

您可以做的一件事是使用模板函数将传递到子模板的变量与父模板中的变量“合并”。type Person struct {&nbsp; &nbsp; FirstName&nbsp; string&nbsp; &nbsp; SecondName string}type Document struct {&nbsp; &nbsp; DocName string&nbsp; &nbsp; People&nbsp; []Person&nbsp; &nbsp; SwitchNameOrder bool}func personWithDocument(p Person, d Document) interface{} {&nbsp; &nbsp; return struct {&nbsp; &nbsp; &nbsp; &nbsp; Person&nbsp; &nbsp; &nbsp; &nbsp; Document Document&nbsp; &nbsp; }{p, d}}t := template.Must(template.New("document").Funcs(template.FuncMap{&nbsp; &nbsp; "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

收到一只叮咚

对于上述复杂的解决方案,更好的解决方案是停止尝试使用顶级配置选项,而是将其编写为模板函数,并将配置变量放在函数闭包中{{- 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{&nbsp; &nbsp; "SwitchNameOrder": func() bool {&nbsp; &nbsp; &nbsp; &nbsp; return switchNames // variable sits in closure&nbsp; &nbsp; },}).Parse(document))https://play.golang.org/p/O6QHtmxweOi另一种选择是将整个切换编写为字符串函数,即:{{- define "person"}}Person name is: {{SwitchNames .FirstName .SecondName}}{{end}}并SwitchNames作为字符串函数...Funcs(template.FuncMap{&nbsp; &nbsp; "SwitchNames": func(first, second string) string {&nbsp; &nbsp; &nbsp; &nbsp; if switchNames {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return second + " " + first&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return first + " " + second&nbsp; &nbsp; },})...可以更干净或更干净,具体取决于实际的复杂性https://play.golang.org/p/UPB3NIpzw0N

蝴蝶刀刀

我最终做的是添加一个单独的结构配置并将其复制到各处。那是,type Config struct {&nbsp; &nbsp; SwitchNameOrder bool}type Person struct {&nbsp; &nbsp; FirstName&nbsp; string&nbsp; &nbsp; SecondName string&nbsp; &nbsp; Config Config&nbsp;&nbsp; &nbsp; // this could also be a pointer,&nbsp; &nbsp; // but I don't want to deal with nils, so let's copy}type Document struct {&nbsp; &nbsp; DocName string&nbsp; &nbsp; People&nbsp; []Person&nbsp; &nbsp; Config Config}和c := Config{SwitchNameOrder: true}d.Config = cfor _, p := range d.People {&nbsp; &nbsp; 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
打开App,查看更多内容
随时随地看视频慕课网APP