You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:01:14