Go模板如何将变量作为嵌套template函数的路径参数使用
Go模板动态引用子模板的解决方案
错误原因
Go标准库的text/template/html/template中,{{template}}动作的第一个参数要求必须是字符串字面量,不支持动态传入变量作为模板名,你当前的写法不符合原生语法规范,因此会抛出unexpected "$" in template clause错误,该问题和转义规则无关。
可行解决方案
方案1:注册自定义include函数(最推荐)
你可以在解析模板前自定义一个模板函数,实现动态加载渲染指定名称模板的能力:
- 后端Go代码中注册自定义函数:
import ( "bytes" "html/template" ) // 初始化模板时注册函数 func initTemplate() (*template.Template, error) { funcMap := template.FuncMap{ "include": func(tplName string, data interface{}) (template.HTML, error) { // 注意:这里的t是预解析了所有子模板的全局模板实例 var buf bytes.Buffer err := t.ExecuteTemplate(&buf, tplName, data) return template.HTML(buf.String()), err }, } // 预解析所有需要用到的子模板到同一个模板实例 t, err := template.New("").Funcs(funcMap).ParseGlob("path/to/templates/*.txt") return t, err }
- 模板中使用自定义函数替代原生
template动作:
blah {{include $.Backends .}} blah
方案2:分支判断渲染(适合可选模板有限的场景)
如果你的可选子模板是可枚举的少量模板,可以直接用条件判断分支写死模板名:
blah {{if eq $.Backends "/path/to/backends.txt"}} {{template "/path/to/backends.txt" .}} {{else if eq $.Backends "/path/to/other.txt"}} {{template "/path/to/other.txt" .}} {{end}} blah
设计原因说明
Go模板默认不支持动态模板名是出于静态校验和安全的设计考虑:模板在解析阶段就会检查所有引用的子模板是否存在,提前发现配置错误;如果允许动态传入模板名,模板缺失的问题只能在运行时触发,会增大线上故障风险。
内容的提问来源于stack exchange,提问作者4m1r
相关产品推荐
相关产品推荐

