Go模板中变量赋值的正确语法与作用域详解
Go语言的text/template和html/template包自1.11版本起支持对已声明变量重新赋值但必须使用空格分隔的$var value语法而非$var:value后者仅用于声明否则赋值无效且无报错。 go语言的text/template和html/template包自1.11版本起支持对已声明变量重新赋值但必须使用空格分隔的$var value语法而非$var:value后者仅用于声明否则赋值无效且无报错。在Go模板中变量具有词法作用域lexical scope其生命周期和可见性由定义位置及嵌套结构严格决定。关键规则如下使用 {{$x : value}} 语法声明新变量作用域为当前模板动作块如 {{range}}、{{with}} 内部不可跨作用域修改自 Go 1.11 起模板支持对同级作用域内已声明的变量进行重新赋值但语法必须是 {{$x new_value}}等号两侧需有空格而非声明式 :{{{with}}、{{range}} 等控制结构会创建新的作用域其内部声明的变量对外不可见若需在循环中维护状态如分组标记变量必须在最外层作用域声明并在循环内用赋值语法更新。以下为修复后的完整示例实现按年份分组输出赛事package mainimport ( fmt os text/template time)func main() { tournaments : []struct { Place string Date time.Time }{ {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.Format 2006-01-02}}{{end}}) if err ! nil { panic(err) } if err : t.Execute(os.Stdout, tournaments); err ! nil { fmt.Println(executing template:, err) }}输出结果 文心快码 文心快码Comate是百度推出的一款AI辅助编程工具