【声明】
非完全原创,部分内容来自于学习其他人的理论和B站视频。如果有侵权,请联系我,可以立即删除掉。
一、html/template
主要参考文档:
(1)Go语言标准库之http/template
(2)Go模板template用法详解
template包(html/template)实现了数据驱动的模板,用于生成可对抗代码注入的安全HTML输出。本包提供了和text/template包相同的接口,无论何时当输出是HTML的时候都应使用本包
在一些前后端不分离的Web架构中,我们通常需要在后端将一些数据渲染到HTML文档中,从而实现动态的网页(网页的布局和样式大致一样,但展示的内容并不一样)效果。
我们这里说的模板可以理解为事先定义好的HTML文档文件,模板渲染的作用机制可以简单理解为文本替换操作–使用相应的数据去替换HTML文档中事先准备好的标记
1、模板引擎
1.1、简介
Go语言内置了文本模板引擎text/template和用于HTML文档的html/template。它们的作用机制可以简单归纳如下:
- 模板文件通常定义为
.tmpl
和.tpl
为后缀(也可以使用其他的后缀),必须使用UTF8编码
。 - 模板文件中使用
{ {
和}}
包裹和标识需要传入的数据。 - 传给模板这样的数据就可以通过点号
.
来访问,如果数据是复杂类型的数据,可以通过{ {.FieldName}}
来访问它的字段。 - 除
{ {
和}}
包裹的内容外,其他内容均不做修改原样输出
1.2、使用流程
分为三部分:定义模板文件、解析模板文件和模板渲染
1.2.1、定义模板文件
定义一个html
文件即可,后缀名成可以设定为 tmpl
或者 tpl
,不过一般使用 tmpl
作为模板文件后缀
1.2.2、解析模板文件
上面定义好了模板文件之后,可以使用下面的常用方法去解析模板文件,得到模板对象
func New(name string) *Template
//创建一个名为name的模板
func (t *Template) Funcs(funcMap FuncMap) *Template
//Funcs方法向模板t的函数字典里加入参数funcMap内的键值对。
//如果funcMap某个键值对的值不是函数类型或者返回值不符合要求会panic。
//但是,可以对t函数列表的成员进行重写。方法返回t以便进行链式调用
func (t *Template) Parse(src string) (*Template, error)
//Parse方法将字符串text解析为模板。嵌套定义的模板会关联到最顶层的t。
//Parse可以多次调用,但只有第一次调用可以包含空格、注释和模板定义之外的文本。
//如果后面的调用在解析后仍剩余文本会引发错误、返回nil且丢弃剩余文本;
//如果解析得到的模板已有相关联的同名模板,会覆盖掉原模板
func ParseFiles(filenames ...string) (*Template, error)
//ParseFiles函数创建一个模板并解析filenames指定的文件里的模板定义。
//返回的模板的名字是第一个文件的文件名(不含扩展名),内容为解析后的第一个文件的内容。
//至少要提供一个文件。如果发生错误,会停止解析并返回nil。
func ParseGlob(pattern string) (*Template, error)
//ParseGlob创建一个模板并解析匹配pattern的文件(参见glob规则)里的模板定义。
//返回的模板的名字是第一个匹配的文件的文件名(不含扩展名),内容为解析后的第一个文件的内容。至少要存在一个匹配的文件。
1.2.3、模板渲染
渲染模板简单来说就是使用数据去填充模板
func (t *Template) Execute(wr io.Writer, data interface{
}) error
//Execute方法将解析好的模板应用到data上,并将输出写入wr。
//如果执行时出现错误,会停止执行,但有可能已经写入wr部分数据。模板可以安全的并发执行。
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{
}) error
//ExecuteTemplate方法类似Execute,但是使用名为name的t关联的模板产生输出
1.3、使用示例
1.3.1、定义index.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Person</title>
</head>
<body>
<p> Id {
{.p.Id}}</p>
<p> Name {
{.p.Name}}</p>
<p> Age {
{.p.Age}}</p>
<p> Address {
{.p.Addr}}</p>
</body>
</html>
1.3.2、代码解析
type Person struct {
Id int
Name string
Age int
Addr string
}
func main() {
http.HandleFunc("/index", func(w http.ResponseWriter, r *http.Request) {
// 根据模板文件生成模板对象
tmpl, err := template.ParseFiles("index.tmpl")
if err != nil {
fmt.Println("parse template failed, err = ", err)
return
}
// 构造数据渲染模板,将结果写入到w
yufei := Person{
Id: 20220821,
Name: "YuFei",
Age: 26,
Addr: "WuHan",
}
//也可写为
/*
yufei = map[string]interface{}{
"Id": 20220821,
"Name": "YuFei",
"Age": 26,
"Addr": "WuHan",
}
*/
err = tmpl.Execute(w, map[string]interface{
}{
"p": yufei,
})
if err != nil {
fmt.Println("execute template failed, err = ", err)