Go模板后处理是否可行?如何对subtemplate输出做缩进等加工操作?
Go模板子模板输出缩进的优雅实现方案
标准Go模板的内置template动作默认直接将内容输出到渲染流,无返回值,因此原生不支持直接对其输出使用管道处理。你可以通过以下两种方案实现需求:
方案1:自定义模板函数(最优雅,推荐)
这是最贴近你期望的管道写法的方案,只需要提前注册两个自定义模板函数即可:
- 首先在Go代码中注册函数,实现子模板执行结果捕获、以及缩进逻辑:
import ( "bytes" "strings" "text/template" ) // 初始化模板时注册自定义函数 var rootTpl *template.Template funcMap := template.FuncMap{ // 执行子模板并返回输出字符串,闭包根模板实例简化调用 "execTpl": func(name string, data any) (string, error) { var buf bytes.Buffer if err := rootTpl.ExecuteTemplate(&buf, name, data); err != nil { return "", err } return buf.String(), nil }, // 对输入字符串按指定空格数缩进每一行,适配YAML格式避免多余空行缩进 "indent": func(spaceNum int, content string) string { prefix := strings.Repeat(" ", spaceNum) return prefix + strings.ReplaceAll(strings.TrimSuffix(content, "\n"), "\n", "\n"+prefix) }, } // 绑定FuncMap到模板实例 rootTpl, err := template.New("root").Funcs(funcMap).ParseGlob("*.tpl")
- 模板中直接使用管道链式调用,和你期望的虚构写法完全一致:
{{ execTpl "subtemplate" . | indent 10 }}
方案2:原生变量捕获(仅修改模板代码)
如果不想修改Go侧逻辑,也可以用标准库原生支持的方式先捕获子模板输出再处理,仅比方案1多1-2行代码:
{{- /* 声明变量捕获子模板输出 */ -}} {{- $subOutput := "" }} {{- template "subtemplate" . | assign &$subOutput }} {{- /* 对捕获的内容做缩进处理 */ -}} {{ indent 10 $subOutput }}
该方案需要注意:标准库原生无assign类赋值函数,你仍需自行实现一个简单的变量写入函数,适配性略低于方案1。
内容的提问来源于stack exchange,提问作者Igor Chubin
相关产品推荐
相关产品推荐

