Golang模板中使用嵌套变量的方法与技巧
Golang模板中使用嵌套变量的方法与技巧 在我的第一个版本中,我刚刚实现了一个函数来插值类似这样的内容:
"{{ .house }} {{ .cosa_rara | upper }} ",使用了以下映射:
varsContent := map[string]interface{}{
"mix": "{{ .house }} {{ .cosa_rara | upper }} ",
"house": "A {{ .the }} casita",
"the": "la {{ .cosa_rara | title }}",
"animal": "de {{ .the | title }} mariposa",
"cosa_rara": "demo_pato",
"mapa": "demo_pato",
"cyclic": "This is a {{ .cyclic }}",
"colour": map[string]interface{}{
"red": "rojo",
"blue": "azul",
"pink": "rosa",
"orange": "{{ mapa }}",
},
}
这次执行的结果是:"A la Demo_pato casita DEMO_PATO "。如你所见,插值是递归执行的,并且工作正常。我现在的问题是,需要实现一种方法来执行这个:"{{ .colour.orange }}",这次执行的结果应该是 “demo_pato”,而在这个问题上……我需要帮助。
非常感谢。
更多关于Golang模板中使用嵌套变量的方法与技巧的实战教程也可以访问 https://www.itying.com/category-94-b0.html
很抱歉,我想我刚刚找到了一个简单得多的解决方案。感谢您抽出时间!!!
你好,
这是测试 https://github.com/judoDsl/interpolator/blob/40d981f685b1447ae1a1720bd0e3c2f18d9973c7/main_test.go#L129。
谢谢!!
在Go模板中访问嵌套变量(如{{ .colour.orange }})时,需要确保数据结构支持点号.导航。根据你提供的varsContent结构,colour是一个嵌套的map[string]interface{},但orange的值是字符串"{{ mapa }}",这会导致模板引擎将其视为字面字符串而非模板表达式。以下是实现方法:
1. 修正数据结构
将colour.orange的值改为直接引用变量(如"demo_pato")或通过模板函数解析。但根据你的需求,若希望{{ .colour.orange }}输出"demo_pato",需要确保mapa变量能被访问。当前mapa在根层级,但colour.orange是字符串,不会自动解析内部模板。建议使用自定义模板函数处理嵌套变量。
2. 使用自定义函数解析嵌套变量
注册一个自定义函数(如getVar),在模板中通过函数调用访问嵌套值。示例:
package main
import (
"bytes"
"fmt"
"strings"
"text/template"
)
func main() {
// 定义数据
varsContent := map[string]interface{}{
"mix": "{{ .house }} {{ .cosa_rara | upper }}",
"house": "A {{ .the }} casita",
"the": "la {{ .cosa_rara | title }}",
"animal": "de {{ .the | title }} mariposa",
"cosa_rara": "demo_pato",
"mapa": "demo_pato",
"cyclic": "This is a {{ .cyclic }}",
"colour": map[string]interface{}{
"red": "rojo",
"blue": "azul",
"pink": "rosa",
"orange": "{{ .mapa }}", // 改为模板表达式
},
}
// 自定义函数:获取嵌套变量值
funcs := template.FuncMap{
"getVar": func(m map[string]interface{}, key string) interface{} {
return m[key]
},
"upper": strings.ToUpper,
"title": strings.Title,
}
// 解析模板
tmplStr := `{{ .colour.orange }}` // 直接访问嵌套map
tmpl, err := template.New("test").Funcs(funcs).Parse(tmplStr)
if err != nil {
panic(err)
}
// 执行模板
var buf bytes.Buffer
err = tmpl.Execute(&buf, varsContent)
if err != nil {
panic(err)
}
fmt.Println("输出:", buf.String()) // 输出: {{ .mapa }}
}
但上述代码中,colour.orange是字符串"{{ .mapa }}",输出会是字面量而非解析后的"demo_pato"。这是因为模板引擎不会递归解析字符串内的模板语法。
3. 递归解析解决方案
若要实现递归解析,需在自定义函数中处理模板字符串。示例:
funcs := template.FuncMap{
"resolve": func(data map[string]interface{}, s string) (string, error) {
tmpl, err := template.New("resolver").Funcs(funcs).Parse(s)
if err != nil {
return "", err
}
var buf bytes.Buffer
err = tmpl.Execute(&buf, data)
return buf.String(), err
},
}
// 在模板中使用:{{ resolve . "{{ .colour.orange }}" }}
但更直接的方法是预处理数据,将colour.orange的值改为变量引用而非字符串模板。例如:
varsContent["colour"].(map[string]interface{})["orange"] = varsContent["mapa"]
然后模板{{ .colour.orange }}将直接输出"demo_pato"。
4. 完整示例:预处理嵌套值
package main
import (
"bytes"
"fmt"
"strings"
"text/template"
)
func main() {
varsContent := map[string]interface{}{
"mapa": "demo_pato",
"colour": map[string]interface{}{
"orange": nil, // 先占位
},
}
// 预处理:将colour.orange指向mapa的值
varsContent["colour"].(map[string]interface{})["orange"] = varsContent["mapa"]
funcs := template.FuncMap{
"upper": strings.ToUpper,
"title": strings.Title,
}
tmpl, _ := template.New("test").Funcs(funcs).Parse(`{{ .colour.orange }}`)
var buf bytes.Buffer
tmpl.Execute(&buf, varsContent)
fmt.Println("输出:", buf.String()) // 输出: demo_pato
}
关键点
- Go模板默认支持通过点号
.访问嵌套map的字段(如{{ .colour.orange }}),但值必须是具体数据而非含模板语法的字符串。 - 若需动态解析嵌套模板字符串,需通过自定义函数递归处理或预处理数据结构。
- 你的案例中,将
colour.orange的值直接设为varsContent["mapa"]是最简洁的解决方案。

