Go语言模板引擎的使用可以分为三部分:定义模板文件、解析模板文件和模板渲染。
定义模板
按照相应的语法编写模板文件。
1
2
3
4
5
6
7
8
|
<html>
<head>
<title>模板文件</title>
</head>
<body>
hello {{ . }}
</body>
</html>
|
Go语言内置了文本模板引擎text/template
和用于HTML文档的html/template
。它们的作用机制可以简单归纳如下:
- 模板文件通常定义为
.tmpl
和.tpl
为后缀(也可以使用其他的后缀),必须使用UTF8
编码。
- 模板文件中使用
{{
和}}
包裹和标识需要传入的数据。
- 传给模板的数据可以通过点号
.
来访问,如果数据是复杂类型的数据,可以通过{{ .FieldName }}
来访问它的字段。
- 除
{{
和}}
包裹的内容外,其他内容均不做修改原样输出。
解析模板
系统定义了一些模板解析方法,获得模板对象
1
2
3
4
5
6
7
8
9
10
11
|
// 创建模板对象,并为其添加一个模板名称
func New(name string) *Template {}
// 解析字符串,比如template.New("name").Parse(src string) 创建模板对象,并完成模板解析。
func (t *Template) Parse(src string) (*Template, error) {}
// 解析模板文件得到模板对象,可以同时解析多个文件
func ParseFiles(filenames ...string) (*Template, error) {}
// 批量解析文件,比如解析当前目录下有以h开头的模板文件:template.ParseGlob("h*")
func ParseGlob(pattern string) (*Template, error) {}
|
解析模板的时候,有几个实用的方法
1
2
3
4
5
6
7
8
|
// 模板包里面有一个函数Must,它的作用是检测模板是否正确。
// 例如大括号是否匹配,注释是否正确的关闭,变量是否正确的书写
func Must(t *Template, err error) *Template
// Funcs方法向模板t的函数字典里加入参数funcMap内的键值对。
// 如果funcMap某个键值对的值不是函数类型或者返回值不符合要求会panic。
// 但是,可以对t函数列表的成员进行重写。方法返回t以便进行链式调用
func (t *Template) Funcs(funcMapFuncMap) *Template
|
模板渲染
模板渲染就是将后台的数据替换模板文件中的特定占位符,这里的特定字符是模板文件中的{{ . }}
。系统定义了两个渲染方法:
1
2
|
func (t *Template) Execute(wr io.Writer, data interface{}) error {}
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {}
|
Execute
用来渲染单个模板,如果是用 ParseFiles,ParseGlob
一次性加载了多个模板,就需要用 ExecuteTemplate
选择模板来解析。
模板语法汇总
模板函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
func xss2(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("demo/tpl/xss2.html")
if err != nil {
fmt.Println("模板解析异常 err = ", err)
return
}
str := "<a href = 'http://www.baidu.com'>百度</a>"
// 此时,我们想在页面上留下百度的跳转链接,但是这样写的话,肯定会被转义
_ = t.Execute(w, str)
}
func xss3(w http.ResponseWriter, r *http.Request) {
// 自定义模板函数,将特定字符串渲染成HTML标签输出显示,不要转义。
// 注意:New传入的模板名不能带路径,下面ParseFiles解析模板则需要带路径
t, err := template.New("xss3.html").Funcs(
template.FuncMap {
"safe": func(s string) template.HTML {
return template.HTML(s)
},
},
).ParseFiles("demo/tpl/xss3.html")
if err != nil {
fmt.Println("模板解析异常 err = ", err)
return
}
str := "<a href = 'http://www.baidu.com'>百度</a>"
_ = t.Execute(w, str)
}
|
模板嵌套
1
2
3
4
5
6
7
8
9
|
// 定义名称为 name 的 template
{{ define "name" }} T {{ end }}
// 执行名为 name 的 template
{{ template "name" }}
{{ template "name" pipeline }}
// 先定义,并执行
{{ block "name" pipeline }} T {{ end }}
|
block
等价于define
定义一个名为name
的模板,并执行这个模板,执行时将.
设置为pipeline
的值。
等价于:先 {{ define "name" }} T {{ end }}
再执行 {{ template "name" pipeline }}
。
参考:
(未完待续…)