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官网模板包

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐