Go 语言内置的 text/template
支持自定义函数功能:
// Funcs adds the elements of the argument map to the template's function map.
// It must be called before the template is parsed.
// It panics if a value in the map is not a function with appropriate return
// type or if the name cannot be used syntactically as a function in a template.
// It is legal to overwrite elements of the map. The return value is the template,
// so calls can be chained.
func (t *Template) Funcs(funcMap FuncMap) *Template {
t.init()
t.muFuncs.Lock()
defer t.muFuncs.Unlock()
addValueFuncs(t.execFuncs, funcMap)
addFuncs(t.parseFuncs, funcMap)
return t
}
简单理解,即通过 Funcs
函数调用,我们可以将自己定义的函数注册到 template 上,就可以在模版里通过 {{ 函数名 }}
方式引用了。云计算圈子里大家熟知的 Helm 就是采用这种方式实现的 yaml 函数渲染!
下面举个简单的栗子:
package main
import (
"math/rand"
"os"
"sort"
"text/template"
"github.com/Masterminds/sprig/v3"
"github.com/lithammer/dedent"
)
var demoTmpl = dedent.Dedent(`
Hello, {{ userinfo }}!
The date is {{ now | date "2006-01-02" }}.
Generates a sorted random string {{ randomstring | sortstring | quote }}
`)
func main() {
// initialize basic func map
funcMap := sprig.TxtFuncMap()
// add our special func `userinfo`
funcMap["userinfo"] = func() string {
return "SataQiu"
}
funcMap["randomstring"] = func() string {
letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
b := make([]rune, 12)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
funcMap["sortstring"] = func(s string) string {
r := []rune(s)
sort.Sort(sortRunes(r))
return string(r)
}
ctx := map[string]interface{}{}
template.Must(template.New("demo").Funcs(funcMap).Parse(demoTmpl)).Execute(os.Stdout, ctx)
}
type sortRunes []rune
func (s sortRunes) Less(i, j int) bool {
return s[i] < s[j]
}
func (s sortRunes) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s sortRunes) Len() int {
return len(s)
}
在这个例子中,我们一共使用了 6 个函数,其中有 3 个(now、date、quote)是 sprig 库已经为我们内置的基础函数,另外 3 个(userinfo、randomstring、sortstring)是我们自己编写的自定义函数。
该例的执行结果如下:
Hello, SataQiu!
The date is 2021-02-08.
Generates a sorted random string "GMVWWZapquvy"
可以看到,自定义函数已经被正确执行并渲染到模版里了!