Go 的 html/template
包为 HTML 模板提供了一种丰富的模板语言。它主要用于 Web 应用程序,以结构化方式在客户端浏览器中显示数据。Go 模板语言的一大好处是自动转义数据。无需担心 XSS 攻击,因为 Go 会解析 HTML 模板并在将其显示到浏览器之前转义所有输入。
在 Go 中编写模板非常简单。此示例显示了一个 TODO 列表,该列表以无序列表 (ul) 的形式写在 HTML 中。呈现模板时,传入的数据可以是 Go 的任何数据结构。它可以是一个简单的字符串或数字,甚至可以是嵌套数据结构,如下面的示例所示。要访问模板中的数据,可以通过 {{.}}
访问最顶层的变量。大括号内的点称为管道,是数据的根元素。
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>
模板语言包含一组丰富的控制结构来呈现 HTML。您将在这里获得最常用的结构的概述。要获取所有可能结构的详细列表,请访问:text/template
控制结构 | 定义 |
---|---|
{{/* 注释 */}} |
定义注释 |
{{.}} |
呈现根元素 |
{{.Title}} |
呈现嵌套元素中的“标题”字段 |
{{if .Done}} {{else}} {{end}} |
定义 if 语句 |
{{range .Todos}} {{.}} {{end}} |
循环遍历所有“待办事项”,并使用 {{.}} 呈现每个待办事项 |
{{block "content" .}} {{end}} |
定义一个名为“content”的块 |
模板可以从字符串或磁盘上的文件解析。通常情况下,模板是从磁盘解析的,此示例演示了如何执行此操作。在此示例中,有一个模板文件与 Go 程序位于同一目录中,名为 layout.html
。
tmpl, err := template.ParseFiles("layout.html")
// or
tmpl := template.Must(template.ParseFiles("layout.html"))
从磁盘解析模板后,即可在请求处理程序中使用该模板。Execute
函数接受一个 io.Writer
用于写入模板,以及一个 interface{}
用于将数据传递到模板中。当在 http.ResponseWriter
上调用该函数时,Content-Type 标头会自动在 HTTP 响应中设置为 Content-Type: text/html; charset=utf-8
。
func(w http.ResponseWriter, r *http.Request) {
tmpl.Execute(w, "data goes here")
}
这是你可以用来尝试本示例中所学内容的完整代码。
package main
import (
"html/template"
"net/http"
)
type Todo struct {
Title string
Done bool
}
type TodoPageData struct {
PageTitle string
Todos []Todo
}
func main() {
tmpl := template.Must(template.ParseFiles("layout.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
tmpl.Execute(w, data)
})
http.ListenAndServe(":80", nil)
}
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>