代碼倉庫 https://github.com/tylitianrui/gotemplate
1.簡述
1.1 高性能
gotemplate 模版引擎是go語言中、性能最高的文本渲染引擎之一。性能是官方text/template的5倍左右,是fasttemplate的1.7~2倍左右。
1.2 自定義佔位符tag
gotemplate 模版引擎允許用户設置自定義的佔位符tag,例如: [[xxx]]、{{.xxx}}、[[(xxx}}、::@xxx$$% 等。匹配到佔位符的文本,則就會被渲染。如果沒有設置佔位符tag,默認使用{{xxx}}。注:xxx 為被替換的參數
| 模版 | 設置的佔位符tag | 實參 (k-v) | 渲染結果 |
|---|---|---|---|
| i am [[(name}} | [[(和 }} |
name:tyltr | i am tyltr |
| i am {{.name}} | {{.和 }} |
name:tyltr | i am tyltr |
| i am ::@name$$% | ::@和 $$% |
name:tyltr | i am tyltr |
1.3 渲染模式
gotemplate 模版引擎有兩種渲染模式:嚴格模式、非嚴格模式
- 嚴格模式:渲染文本中的每個佔位符。如果要求的參數缺少,就會報錯。
- 非嚴格模式:盡最大努力渲染文本。如果參數缺少,則不渲染或者自動填充默認值
2.基本使用
2.1 非嚴格模式,不設置自動填充
package main
import (
"fmt"
"github.com/tylitianrui/gotemplate"
)
func main() {
tpl := "https://{{demain}}.com?name={{name}}&age={{age}}&birth={{birth}}"
// Create a new template instance with default tag pair `{{` &` }}` and pre-allocated memory of 1024 bytes.
t, err := gotemplate.NewTemplate(tpl,
gotemplate.WithPreAllocateMemory(1024), // Pre-allocate memory for better performance ,1024 bytes
)
if err != nil {
panic(err)
}
// Substitution map.
// "birth" tag is missing in the map
args := map[string]string{
"demain": "user.google",
"bar": "foobar",
"name": "tyltr",
"age": "18",
// "birth" is missing.
}
// Non-strict mode, placeholders without corresponding entries in args will remain unchanged in the output.
s, err := t.ExecString(args, false)
fmt.Println("err:", err)
fmt.Println("template:", s)
// Output:
// err: <nil>
// template: https://user.google.com?name=tyltr&age=18&birth={{birth}}
}
説明:
- 本例子中沒有設置自定義的佔位符tag,則使用默認的
{{和}}匹配 -
t.ExecString(args, false)第二個參數定義為strict bool- false 則是非嚴格模式
- true 則為嚴格模式
2.2 非嚴格模式,自動填充
package main
import (
"fmt"
"github.com/tylitianrui/gotemplate"
)
func main() {
tpl := "https://[[demain]].com?name=[[name]]&age=[[age]]&birth=[[birth]]"
t, err := gotemplate.NewTemplate(tpl,
gotemplate.WithTagPair("[[", "]]"), // set custom tag pair `[[` & `]]`
gotemplate.WithPreAllocateMemory(1024), // Pre-allocate memory for better performance ,1024 bytes
gotemplate.WithAutoFill(""), // Auto fill missing parameters with empty string
)
if err != nil {
panic(err)
}
// Substitution map.
// "birth" tag is missing in the map
args := map[string]string{
"demain": "user.google",
"bar": "foobar",
"name": "tyltr",
"age": "18",
// "birth" is missing.
}
// Non-strict mode, placeholders without corresponding entries in args will remain unchanged in the output.
s, err := t.ExecString(args, false)
fmt.Println("err:", err)
fmt.Println("template:", s)
// Output:
// err: <nil>
// template: https://user.google.com?name=tyltr&age=18&birth=
}
説明:
gotemplate.WithAutoFill("")設置自動填充字段,本例子設置為空字符串填充
2.3 嚴格模式
package main
import (
"fmt"
"github.com/tylitianrui/gotemplate"
)
func main() {
tpl := "https://{{demain}}.com?name={{name}}&age={{age}}&birth={{birth}}"
t, err := gotemplate.NewTemplate(tpl,
gotemplate.WithTagPair("{{", "}}"),
gotemplate.WithPreAllocateMemory(1024),
)
if err != nil {
panic(err)
}
// Substitution map.
// "birth" tag is missing in the map
args := map[string]string{
"demain": "user.google",
"bar": "foobar",
"name": "tyltr",
"age": "18",
// "birth" is missing.
}
// strict mode, it returns an error if any placeholder in the template does not have a corresponding entry in args.
s, err := t.ExecString(args, true)
fmt.Println("err:", err)
fmt.Println("template:", s)
// Output:
// err: missing parameter
// template:
}
説明:
- 參數
birth缺少,則報錯missing parameter
3.高級用法
高級用法允許用户動態的調整渲染的字段
package main
import (
"bytes"
"fmt"
"io"
"github.com/tylitianrui/gotemplate"
)
func main() {
tpl := "https://{{demain}}.com?name={{name}}&age={{age}}&birth={{birth}}"
t, err := gotemplate.NewTemplate(tpl)
if err != nil {
panic(err)
}
var buf bytes.Buffer
err = t.ExecuteFunc(&buf, func(w io.Writer, key string) (int, error) {
switch key {
case "demain":
return w.Write([]byte("user.google"))
case "name":
return w.Write([]byte("tyltr"))
case "age":
return w.Write([]byte("18"))
default:
return w.Write([]byte("<null>")) // Auto fill missing parameters with "<null>"
}
})
fmt.Println("err:", err)
fmt.Println("template:", buf.String())
// Output:
//err: <nil>
//template: https://user.google.com?name=tyltr&age=18&birth=<null>
}
4.匹配優先級
一般配置模版都是{{和}}、[[和]]等成對出現的。但對於特殊情況,例如 {{{name{{}}age}} 怎麼渲染呢?這些"噁心"的模板遵守以下規範
4.1佔位符為空,被當作普通文本
| 案例 | 模版 | 標籤 | 參數(map類型) | 效果 |
|---|---|---|---|---|
| 案例1 | hello,i am {{name}} |
{{和 }} |
name:tyltr |
hello,i am tyltr |
| 案例2 | hello,i am {{}} {{name}} | {{和 }} |
name:tyltr |
hello,i am {{}} tyltr |
説明:案例2中包含空佔位符 {{}} 會當作普通文本展示。
4.2 非貪婪模式匹配佔位符
| 案例 | 模版 | 標籤 | 佔位符 | 參數(map類型) | 效果 |
|---|---|---|---|---|---|
| 案例3 | hello,i am {{{name}} |
{{和 }} |
name 而不是{name |
name:tyltr |
hello,i am {tyltr |
説明:案例3 匹配採用非貪婪模式,會匹配儘可能少的字符。所以匹配出的佔位符為 name 而不是{name
4.3 最左側匹配原則
| 案例 | 模版 | 標籤 | 佔位符 | 參數(map類型) | 效果 |
|---|---|---|---|---|---|
| 案例4 | hello,i am {{{name{{}}tyltr}} |
{{和 }} |
name{{ 而不是}}tyltr |
name{{:ty |
hello,i am {tytyltr |
説明:
{{{name{{}}tyltr}}中間佔位符為空,所以 {{}} 被當做普通文本處理- 根據最左側匹配原則 左側
{{{name{{}}擁有比右側{{}}tyltr}}更高優先級 - 根據非貪婪原則,左側部分會如此匹配
{{{name{{}}