Golang模板能否将自定义函数用作模板块?
Go模板中实现自定义块级函数的方案
答案是可行的,但原生Go模板不支持直接将自定义函数作为{{ func }}...{{ end }}这种块级指令使用,不过可以通过模板嵌套和片段定义的机制完美模拟你想要的效果。
核心实现思路
- 预定义用于包裹内容的模板片段,比如
note,片段内部实现内容的格式化逻辑(比如包裹指定HTML标签) - 通过
block动作或者自定义函数配合模板片段,让编写者可以直观地输入大段带格式的内容
贴近需求的实现示例
模板写法(完全符合你的预期)
Author is writing something normal... {{ block "note" . }} But would like to wrap this content as a "note". Which when passed to the "note" function, will wrap the content with appropriate divs etc. {{ end }}
Go代码实现
package main import ( "bytes" "fmt" "html/template" "os" ) func main() { // 预定义note模板的处理逻辑 baseTmpl := `{{ define "note" }} <div class="note" style="padding:10px; border:1px solid #ccc; border-radius:4px;"> {{ . }} </div> {{ end }}` // 主模板内容 mainTmpl := ` Author is writing something normal... {{ block "note" . }} But would like to wrap this content as a "note". Which when passed to the "note" function, will wrap the content with appropriate divs etc. {{ end }} ` // 先解析预定义模板,再解析主模板 tmpl, err := template.New("base").Parse(baseTmpl) if err != nil { fmt.Fprintln(os.Stderr, err) return } tmpl, err = tmpl.Parse(mainTmpl) if err != nil { fmt.Fprintln(os.Stderr, err) return } // 执行模板 var buf bytes.Buffer if err = tmpl.Execute(&buf, nil); err != nil { fmt.Fprintln(os.Stderr, err) return } fmt.Println(buf.String()) }
进阶:自定义函数配合内容捕获
如果需要更灵活的逻辑(比如动态传递参数给处理函数),可以用自定义函数捕获模板片段内容:
// 定义自定义函数 funcMap := template.FuncMap{ "note": func(content template.HTML) template.HTML { // 这里可以添加更复杂的处理逻辑,比如添加自定义类、处理换行等 return template.HTML(fmt.Sprintf(`<div class="note">%s</div>`, content)) }, } // 模板写法 tmplContent := ` Author is writing something normal... {{ note (template "note-content") }} {{ define "note-content" }} But would like to wrap this content as a "note". Which when passed to the "note" function, will wrap the content with appropriate divs etc. {{ end }} `
总结
这种方案完全可以满足你现阶段的实验需求:模板编写者可以直观输入保留换行、格式的大段文本,无需手动转义或用字符串包裹。等后续切换到PEG解析器时,也可以平滑过渡,不会有技术冲突。
内容的提问来源于stack exchange,提问作者Andre
相关产品推荐
相关产品推荐

