icz*_*cza 5

简短的回答是:你做不到.

{{$currentUserId := .UserData.UserId}}{{if}}{{end}}
text/templatehtml/template

变量的范围扩展到声明它的控制结构("if","with"或"range")的"end"动作,或者如果没有这样的控制结构则延伸到模板的末尾.模板调用不会从其调用点继承变量.

可能的解决方法

CurrentUserId()UserDataUserData.UserId()0

这是一个如何完成它的例子:

type UserData struct {
    UserId int
}

func main() {
    m := map[string]interface{}{}
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "CurrentUserId": func() int {
            if u, ok := m["UserData"]; ok {
                return u.(UserData).UserId
            }
            return 0
        },
    }).Parse(src))

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
    m["UserData"] = UserData{99}
    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const src = `Current user id: {{CurrentUserId}}
`
UserDataUserDataUserId = 99
Current user id: 0
Current user id: 99

在Go Playground尝试一下.

模拟可变变量

SetCurrentUserId()
mapSetCurrentUserId()
func main() {
    m := map[string]interface{}{}
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "SetCurrentUserId": func(id int) string {
            m["CurrentUserId"] = id
            return ""
        },
    }).Parse(src))

    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
    m["UserData"] = UserData{99}
    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const src = `Before: {{.CurrentUserId}}
{{if .UserData}}
    {{SetCurrentUserId .UserData.UserId}}Inside: {{.CurrentUserId}}
{{else}}
    {{SetCurrentUserId 0}}Inside: {{.CurrentUserId}}
{{end}}
After: {{.CurrentUserId}}
`
UserDataUserDataUserId = 99
Before: 
    Inside: 0
After: 0
Before: 0
    Inside: 99
After: 99

在Go Playground尝试一下.