Go标准库http/template | 青训营笔记

112 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第13天

html/template包实现了数据驱动的模板,用于生成可防止代码注入的安全的HTML内容。它提供了和text/template包相同的接口,Go语言中输出HTML的场景都应使用html/template这个包。


模板与渲染

在一些前后端不分离的Web架构中,我们通常需要在后端将一些数据渲染到HTML文档中,从而实现动态的网页(网页的布局和样式大致一样,但展示的内容并不一样)效果。

我们这里说的模板可以理解为事先定义好的HTML文档文件,模板渲染的作用机制可以简单理解为文本替换操作–使用相应的数据去替换HTML文档中事先准备好的标记。

很多编程语言的Web框架中都使用各种模板引擎,比如Python语言中Flask框架中使用的jinja2模板引擎。


Go语言的模板引擎

Go语言内置了文本模板引擎text/template和用于HTML文档的html/template。它们的作用机制可以简单归纳如下:

  1. 模板文件通常定义为.tmpl和.tpl为后缀(也可以使用其他的后缀),必须使用UTF8编码。

  2. 模板文件中使用{{和}}包裹和标识需要传入的数据。

  3. 传给模板这样的数据就可以通过点号(.)来访问,如果数据是复杂类型的数据,可以通过{ { .FieldName }}来访问它的字段。

  4. 除{{和}}包裹的内容外,其他内容均不做修改原样输出。

模板引擎的使用

可以分为三部分:定义模板文件解析模板文件模板渲染

定义模板文件

详细见后

解析模板文件

使用下面的常用方法去解析模板文件,得到模板对象:

func (t *Template) Parse(src string) (*Template, error)//解析字符串

func ParseFiles(filenames ...string) (*Template, error)//解析文件

func ParseGlob(pattern string) (*Template, error)//只要符合.tmpl的全都解析

也可以使用func New(name string) *Template函数创建一个名为name的模板,然后对其调用上面的方法去解析模板字符串或模板文件。

模板渲染

使用数据去填充模板

//传任意数据(空接口)给wr
func (t *Template) Execute(wr io.Writer, data interface{}) error

//当解析很多模板时
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error

示例:

定义模板./hello.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>Hello World</title>
</head>
<body>
    <p>Hello {{.}}</p>
</body>
</html>

解析和渲染模板文件

然后我们创建一个main.go文件,在其中写下HTTP server端代码如下:

func sayHello(w http.ResponseWriter, r *http.Request) {
        // 解析指定文件生成模板对象
        tmpl, err := template.ParseFiles("./hello.tmpl")
        if err != nil {
                fmt.Println("create template failed, err:", err)
                return
        }
        // 利用给定数据渲染模板,并将结果写入w
        tmpl.Execute(w, "World!")}
func main() {
        http.HandleFunc("/", sayHello)
        err := http.ListenAndServe(":9090", nil)
        if err != nil {
                fmt.Println("HTTP server failed,err:", err)
                return
        }}

定义模板的语法

{{.}}

模板语法都包含在{{和}}中间,其中{{.}}中的点表示当前对象。

当我们传入一个结构体对象时,我们可以根据.来访问结构体/Map的对应字段。