Go模板中嵌套模板作为变量时的变量解析实现方案问询
Go模板实现嵌套模板变量并支持自定义函数
要解决子模板字符串未被解析的问题,核心思路是通过自定义模板函数动态编译并执行子模板,同时让子模板继承主模板的FuncMap,确保自定义函数能正常使用。
具体实现方案
1. 定义数据结构与主模板
先定义包含子模板字符串的结构体,以及主模板内容:
type Todo struct { Name string Subtemplate string // 存储带模板语法的字符串 } const mainTemplate = ` <div> <h1>{{.Name}}</h1> <div class="sub-content"> {{parseSub .Subtemplate .}} </div> </div> `
2. 自定义动态解析函数
在FuncMap中添加一个函数,负责接收子模板字符串和当前渲染上下文,动态编译执行子模板。这里通过闭包引用主模板实例,让子模板自动继承主模板的自定义函数:
func parseSub(tplStr string, data interface{}) (string, error) { // 基于主模板创建子模板,继承其FuncMap subTpl, err := mainTpl.New("dynamic-sub").Parse(tplStr) if err != nil { return "", err } var buf bytes.Buffer if err := subTpl.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil }
3. 完整执行示例
结合自定义函数、主模板解析与数据渲染的完整代码:
package main import ( "bytes" "html/template" "os" "strings" ) type Todo struct { Name string Subtemplate string } func main() { // 定义模板函数集合,包含自定义解析函数和业务函数 funcMap := template.FuncMap{ "parseSub": func(tplStr string, data interface{}) (string, error) { subTpl, err := mainTpl.New("dynamic-sub").Parse(tplStr) if err != nil { return "", err } var buf bytes.Buffer if err := subTpl.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil }, "upper": func(s string) string { return strings.ToUpper(s) }, } // 解析主模板并关联函数集合 mainTpl, err := template.New("main").Funcs(funcMap).Parse(mainTemplate) if err != nil { panic(err) } // 测试数据:子模板中使用变量和自定义函数 todo := Todo{ Name: "嵌套模板测试", Subtemplate: "子模板内容:{{.Name}} | 大写转换:{{upper .Name}}", } // 执行主模板输出结果 if err := mainTpl.Execute(os.Stdout, todo); err != nil { panic(err) } }
4. 优化:缓存子模板
如果子模板字符串重复使用,可添加缓存避免重复编译,提升性能:
var tplCache = make(map[string]*template.Template) func parseSub(tplStr string, data interface{}) (string, error) { if cachedTpl, ok := tplCache[tplStr]; ok { var buf bytes.Buffer if err := cachedTpl.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil } subTpl, err := mainTpl.New("dynamic-sub").Parse(tplStr) if err != nil { return "", err } tplCache[tplStr] = subTpl var buf bytes.Buffer if err := subTpl.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil }
内容的提问来源于stack exchange,提问作者Adam Bogdan Boczek
相关产品推荐
相关产品推荐

