在Go语言里, html/template 包主要用于安全地生成HTML输出。它能够有效防止跨站脚本攻击(XSS),借助模板语法将数据动态填充到HTML文件中。
模板的定义与解析
借助 template.New
和 template.ParseFiles
或者 template.ParseGlob
方法,能够定义并解析模板文件。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
// 创建一个新的模板
tmpl := template.New("example")
// 解析模板文件
tmpl, err := tmpl.ParseFiles("example.tmpl")
if err != nil {
log.Fatal(err)
}
// 定义数据
data := struct {
Name string
}{
Name: "John Doe",
}
// 执行模板并将结果输出到标准输出
err = tmpl.Execute(os.Stdout, data)
if err != nil {
log.Fatal(err)
}
}
模板文件示例(example.tmpl)
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example Template</title>
</head>
<body>
<h1>Hello, {{.Name}}!</h1>
</body>
</html>
条件语句
在模板里能够使用条件语句来依据数据展示不同内容。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
tmpl, err := template.ParseFiles("conditional.tmpl")
if err != nil {
log.Fatal(err)
}
data := struct {
IsAdmin bool
}{
IsAdmin: true,
}
err = tmpl.Execute(os.Stdout, data)
if err != nil {
log.Fatal(err)
}
}
条件模板文件示例(conditional.tmpl)
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Conditional Template</title>
</head>
<body>
{{if .IsAdmin}}
<p>You are an admin!</p>
{{else}}
<p>You are a regular user.</p>
{{end}}
</body>
</html>
循环语句
在模板中可使用循环语句来遍历切片或者映射。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
tmpl, err := template.ParseFiles("loop.tmpl")
if err != nil {
log.Fatal(err)
}
data := []string{"Apple", "Banana", "Cherry"}
err = tmpl.Execute(os.Stdout, data)
if err != nil {
log.Fatal(err)
}
}
循环模板文件示例(loop.tmpl)
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Loop Template</title>
</head>
<body>
<ul>
{{range .}}
<li>{{.}}</li>
{{end}}
</ul>
</body>
</html>
嵌套模板
可以在一个模板里包含另一个模板。
可以使用 {{template "templateName" .}}
来调用并执行定义好的模板块。其中,.
表示传递给模板块的数据。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
tmpl, err := template.ParseFiles("base.tmpl", "header.tmpl")
if err != nil {
log.Fatal(err)
}
data := struct {
Title string
}{
Title: "Nested Template Example",
}
err = tmpl.ExecuteTemplate(os.Stdout, "base.tmpl", data)
if err != nil {
log.Fatal(err)
}
}
基础模板文件示例(base.tmpl)
xml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.Title}}</title>
</head>
<body>
{{template "header.tmpl" .}}
<p>Main content goes here.</p>
</body>
</html>
头部模板文件示例(header.tmpl)
css
<header>
<h1>{{.Title}}</h1>
</header>
define
指令的作用
define
指令用于在模板文件中定义一个命名的模板块。这个模板块可以在同一个模板文件或者其他模板文件中被调用和执行。通过使用 define
指令,你可以将重复的 HTML 代码片段封装成可复用的模块,提高代码的可维护性和复用性。
基本语法
在模板文件中,使用 {{define "templateName"}}
来开始定义一个模板块,使用 {{end}}
来结束定义。其中,templateName
是你为这个模板块指定的名称。
xml
{{define "templateName"}}
<!-- 这里是模板块的内容 -->
{{end}}
单个模板文件中使用 define
以下是一个示例,展示了如何在单个模板文件中定义和使用模板块。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
tmpl, err := template.ParseFiles("single_template.tmpl")
if err != nil {
log.Fatal(err)
}
data := struct {
Title string
}{
Title: "Single Template Example",
}
err = tmpl.ExecuteTemplate(os.Stdout, "main", data)
if err != nil {
log.Fatal(err)
}
}
single_template.tmpl
xml
{{define "header"}}
<header>
<h1>{{.Title}}</h1>
</header>
{{end}}
{{define "main"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.Title}}</title>
</head>
<body>
{{template "header" .}}
<p>Main content goes here.</p>
</body>
</html>
{{end}}
在这个示例中,我们在 single_template.tmpl
文件中定义了两个模板块:header
和 main
。在 main
模板块中,我们使用 {{template "header" .}}
调用了 header
模板块。
多个模板文件中使用 define
以下是一个示例,展示了如何在多个模板文件中定义和使用模板块。
go
package main
import (
"html/template"
"log"
"os"
)
func main() {
tmpl, err := template.ParseFiles("base.tmpl", "header.tmpl")
if err != nil {
log.Fatal(err)
}
data := struct {
Title string
}{
Title: "Multiple Templates Example",
}
err = tmpl.ExecuteTemplate(os.Stdout, "base", data)
if err != nil {
log.Fatal(err)
}
}
header.tmpl
css
{{define "header"}}
<header>
<h1>{{.Title}}</h1>
</header>
{{end}}
base.tmpl
xml
{{define "base"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{.Title}}</title>
</head>
<body>
{{template "header" .}}
<p>Main content goes here.</p>
</body>
</html>
{{end}}
在这个示例中,我们将 header
模板块定义在 header.tmpl
文件中,将 base
模板块定义在 base.tmpl
文件中。在 base
模板块中,我们使用 {{template "header" .}}
调用了 header
模板块。
注意事项
- 当使用
ParseFiles
或ParseGlob
解析多个模板文件时,所有定义的模板块都会被加载到同一个模板集合中,因此可以在不同的模板文件中相互调用。 - 传递给
template
指令的数据可以是任意类型,只要在模板块中能够正确处理即可。