Golang 字符串模板处理
Golang的template包用于解析字符串模板,语法采用Mustache 语法,使用非常简单。
1. 目标
新增下面模板文件,后面需要解析该文件:
{{.Product}} of {{.Company}}
{{if .ProductList -}}
ProductList:
{{- range .ProductList}}
* {{. -}}
{{end}}
{{end}}
像{{.Product}} 和 {{.Company}}作为模板变量在解析时会被替换。其他{{if}} 和 {{range}}是动作,也会被评估执行。在{{}}两边的横杠-
用于去除变量两边的空格。.
表示迭代变量。
2. 解析模板
2.1. 搭建项目
项目结构如下,main.go作为客户端进行测试,关键是process.go实现模板处理逻辑。
go-template-processing/
├── main.go
├── biz
│ └── process.go
└── templates
└── got.tmpl
2.2. 解析模板
首先是解析模板,然后是插值(替换模板中的变量)。Go将包括插值表达式作为执行模板,后续使用数据进行替换,从而实现数据和模板分离。首先定义process
方法:
package biz
import (
"bytes"
"text/template"
)
func process(t *template.Template, vars interface{}) string {
var tmplBytes bytes.Buffer
err := t.Execute(&tmplBytes, vars)
if err != nil {
panic(err)
}
return tmplBytes.String()
}
该方法几乎是自解释,比较容易理解。参数vars是空interface,所以可以是任意数据类型,如map或Struct,只要包括模板表达式中的变量。如果找不对应的变量则输出结果为<no value>
,或解析错误抛异常。
该方法传入Template指针,后续方法可以重用。
2.3. 处理字符串模板
下面函数用于处理字符串模板,通过New方法创建模板用于解析str参数。处理结果赋给tmpl,其中处理国际调用前面的process方法。
func ProcessString(str string, vars interface{}) string {
tmpl, err := template.New("tmpl").Parse(str)
if err != nil {
panic(err)
}
return process(tmpl, vars)
}
2.4. 处理模板文件
该函数与ProcessString模板类似,只是处理模板文件:
func ProcessFile(fileName string, vars interface{}) string {
tmpl, err := template.ParseFiles(fileName)
if err != nil {
panic(err)
}
return process(tmpl, vars)
}
ParseFiles
函数接收多个文件名作为参数,这里仅解析一个文件。
两个处理函数定义好,下面开始测试。
2.5. 变量测试
首先在main.go中定义testVar
方法:
func testVar() {
// data structure the template will be applied to
vars := make(map[string]interface{})
vars["Product"] = "Books"
vars["Company"] = "DangDang"
vars["ProductList"] = []string{"Brave", "Loyal"}
// process a template string
resultA := biz.ProcessString("{{.Product}} of {{.Company}}", vars)
// process a template file
resultB := biz.ProcessFile("templates/got.tmpl", vars)
fmt.Println(resultA)
fmt.Println(resultB)
}
然后再main方法中调用:
func main() {
testVar()
}
运行输出结果为:
Books of DangDang
Books of DangDang
ProductList:
* Brave
* Loyal
字符串模板和文件模板都解析成功。解析结果可以作为邮件内容、文件内容等。
2.6. Struct测试
前面提及参数为interface,既然变量可以,Struct也应该能适用。
我们定义结构体作为参数进行解析:
func testStruct() {
// using a Struct
type ProductInfo struct {
Product string
Company string
ProductList []string
}
huaWeiStr := ProductInfo{"MobilePhone", "HuaWei", []string{"Mate 30", "Nova 7"}}
resultC := biz.ProcessFile("templates/got.tmpl", huaWeiStr)
fmt.Println(resultC)
}
在main方法中调用该函数输出:
MobilePhone of HuaWei
ProductList:
* Mate 30
* Nova 7
3. 总结
使用Golang的默认模板非常直接、简单。本文仅介绍一部分内容,更多内容请参考Go官网模板包。