59、Go语言基础 - Web 编程 - html-template 模板
hi,我是温新
Go 语言中的 html/template 包是一个用于生成 HTML、XML 等格式文本的模板系统。它提供了一种简单的方式来生成文本输出,并支持各种数据类型的嵌入。
Go语言的模板引擎
Go语言内置了文本模板引擎text/template
和用于HTML文档的html/template
。
- 1、模板文件通常定义为
.tmpl
和.tpl
为后缀(也可以使用其他的后缀),必须使用UTF8
编码; - 2、模板文件中使用
{{
和}}
包裹和标识需要传入的数据; - 3、传给模板的数据通过
.
来访问,若数据比较复杂,通过{{.FieldName}}
来访问; - 4、除
{{
和}}
包裹的内容外,其他内容均不做修改原样输出。
模板引擎的使用
Go 语言模板引擎的使用可以分为三部分:定义模板文件、解析模板文件和模板渲染.
解析模板文件
1、template.ParseFiles
使用template.ParseFiles
解析文件:template.ParseFiles
函数用于解析一个或多个模板文件,并返回一个*template.Template
对象。可以传递一个或多个文件名作为参数,用逗号分隔。该函数会将文件内容解析为模板。
tmpl, err := template.ParseFiles("template1.html", "template2.html")
2、template.ParseGlob
使用template.ParseGlob
解析多个文件:template.ParseGlob
函数允许使用通配符匹配多个文件并解析它们。它会将匹配到的所有文件内容合并成一个模板。
tmpl, err := template.ParseGlob("templates/*.html")
3、template.New
使用template.New
创建模板对象:使用template.New
创建一个新的模板对象,然后使用其Parse
或ParseFiles
方法将模板内容添加到该对象中。
tmpl := template.New("example")
tmpl, err := tmpl.Parse("...template content...")
4、template.Must
使用template.Must
包装解析操作:通常,在解析模板时,可以使用template.Must
来简化错误处理。template.Must
接受一个模板解析函数并返回一个不可变的模板。如果解析失败,它会导致程序崩溃,适用于只有在模板格式正确的情况下才能运行的情况。
tmpl := template.Must(template.ParseFiles("template.html"))
模板渲染
模板渲染是将模板与数据结合以生成最终文本输出的过程。在Go语言中,模板渲染通常使用html/template
包进行。
1、Execute
template.Execute
方法用于将数据传递给模板并生成渲染后的输出。这是最常用的渲染方法,可以将数据直接传递给模板进行渲染。
tmpl.Execute(w, data)
2、ExecuteTemplate
template.ExecuteTemplate
方法允许选择要渲染的具体模板。
tmpl.ExecuteTemplate(w, "main", data)
3、ExecuteTemplate
如果模板包含嵌套模板,可以使用template.ExecuteTemplate
方法来渲染嵌套模板。
tmpl.ExecuteTemplate(w, "header", data)
tmpl.ExecuteTemplate(w, "content", data)
tmpl.ExecuteTemplate(w, "footer", data)
4、ExecuteTemplate
ExecuteTemplate
方法与嵌套模板:在嵌套模板的情况下,可以使用{{template "TemplateName" .}}
语法在模板中调用其他模板,然后使用template.Execute
或template.ExecuteTemplate
方法进行渲染。
tmpl.ExecuteTemplate(w, "main", data)
基本案例
定义模板文件
定义一个 1-index.tmpl
模板文件,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Go Web</title>
</head>
<body>
<h1>Go Web 编程</h1>
<h2>{{.}}</h2>
</body>
</html>
Go 解析和渲染模板文件
创建一个 1-index.go
文件,内容如下:
package main
import (
"fmt"
"html/template"
"net/http"
)
func main() {
// 创建 HTTP 服务器,监听在本地的 20000 端口
http.HandleFunc("/go/web", helloHandler) // 注册路由
http.ListenAndServe(":20000", nil) // 启动服务器
}
func helloHandler(w http.ResponseWriter, r *http.Request) { // 定义路由处理函数
tmpl, err := template.ParseFiles("./1-index.tmpl") // 解析模板文件
if err != nil { // 如果解析失败
fmt.Println("create template failed, err:", err)
return
}
// 使用渲染模板,并将结果写入HTTP响应
// 第二个参数"自如初"会替换模板中的占位符
tmpl.Execute(w, "自如初") // 执行模板
}
html/template 模板语法
{{.}}
模板语法都包含在{{
和}}
中间,其中{{.}}
中的点表示当前对象。如 {{.Name}}
注释
{{/* 我是注释 */}}
pipeline
在 Go 语言的模板中,可以使用管道(pipeline)来对多个变量进行处理,以生成最终的输出。管道由多个操作符(operator)组成,操作符可以是内置的函数,也可以是自定义的函数。
模板案例:
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
</head>
<body>
{{/* 将 Title 变量的值转换为大写 */}}
{{.Title | toupper}}
<h1>{{.Message}}</h1>
{{/* 使用自定义函数将 Message 变量的值进行处理 */}}
{{.Message | myFilter}}
</body>
</html>
在上面的模板中,|
操作符用于将一个变量传递给一个函数进行处理。toupper
是一个内置的函数,用于将字符串转换为大写,而 myFilter
则是一个自定义的函数,用于对字符串进行处理。
下面是 toupper
和 myFilter
函数的实现:
func toupper(s string) string {
r := strings.NewReplacer("a", "A", "b", "B", "c", "C", ...)
return r.Replace(s)
}
func myFilter(s string) string {
// 对字符串进行处理,返回处理后的字符串
return s
}
变量
在 Go 语言的模板中,可以使用 {{.}}
语法来获取模板中的当前值。这个值可以是一个变量、一个函数调用、一个控制结构语句等等。
如果想将当前值赋给一个变量,可以使用 $obj := {{.}}
语法。这个语法将会把当前值赋给 $obj
变量。
go 程序案例
package main
import (
"html/template"
"net/http"
)
func main() {
// 创建一个模板对象
tmpl := template.Must(template.ParseFiles("template.html"))
// 渲染模板,并将变量传递给模板
tmpl.Execute(http.ResponseWriter, map[string]interface{}{
"Name": "John",
"Age": 30,
})
}
下面是一个示例,展示了如何使用 $obj := {{.}}
语法:
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
</head>
<body>
<h1>{{.Name}}</h1>
<p>Age: {{.Age}}</p>
<!-- 将 Age 变量的值赋给 $obj 变量 -->
<script>
var obj = {{$obj := .Age}}
console.log(obj);
</script>
</body>
</html>
在上面的模板中,我们首先输出了变量 Name
和 Age
的值。然后,我们使用 {{$obj := .Age}}
语法将变量 Age
的值赋给 $obj
变量。最后,我们使用 console.log
方法输出了 $obj
变量的值。
移除空格
{{- .Name -}}
{{-
语法去除模板内容左侧的所有空白符号, 使用-}}
去除模板内容右侧的所有空白符号。
注意:-
要紧挨{{
和}}
,同时与模板值之间需要使用空格分隔。
条件判断
1、{{if}}
条件语句
{{if condition}}
// 如果 condition 为 true,则执行这里的代码
{{end}}
2、{{if}}
嵌套语句
{{if condition1}}
{{if condition2}}
// 如果 condition1 和 condition2 都为 true,则执行这里的代码
{{else}}
// 如果 condition1 为 true,但 condition2 为 false,则执行这里的代码
{{end}}
{{else}}
// 如果 condition1 为 false,则执行这里的代码
{{end}}
3、{{else}}
语句
{{if condition}}
// 如果 condition 为 true,则执行这里的代码
{{else}}
// 如果 condition 为 false,则执行这里的代码
{{end}}
4、{{else if}}
语句
{{if condition1}}
// 如果 condition1 为 true,则执行这里的代码
{{else if condition2}}
// 如果 condition1 为 false,但 condition2 为 true,则执行这里的代码
{{else}}
// 如果 condition1 和 condition2 都为 false,则执行这里的代码
{{end}}
range
在 Go 的 html/template
包中,{{range ...}} ... {{end}}
结构用于在模板中迭代切片、数组、映射等数据结构的元素,以便渲染模板内容。
以下是有关 {{range ...}}
结构的详细说明:
-
{{range .Slice}} ... {{end}}
:这是基本的range
结构,其中.Slice
表示要迭代的切片或数组。在{{range ...}}
结构内部,你可以使用点号 (.
) 来引用当前迭代的元素。 -
{{range .Slice}} ... {{else}} ... {{end}}
:这是{{range ...}}
结构的扩展版本,它允许你指定一个{{else}}
部分。如果.Slice
为空或不存在,{{else}}
部分将被执行。 -
{{range $index, $element := .Slice}} ... {{end}}
:这种形式的range
结构允许你在循环中访问元素的索引和值,分别用$index
和$element
表示。这对于需要了解元素索引的情况非常有用。 -
{{range .Map}} ... {{end}}
:除了切片和数组,range
也可以用于映射 (map)。在这种情况下,{{.Map}}
表示要迭代的映射,循环中的.Key
和.Value
分别表示键和值。 -
{{range $key, $value := .Map}} ... {{end}}
:与上面的类似,这种形式的range
结构允许你访问映射中的键和值,分别用$key
和$value
表示
下面是一个简单的示例,演示如何在模板中使用 {{range ...}}
结构遍历切片:
{{range .Users}}
<p>Name: {{.Name}}, Age: {{.Age}}</p>
{{else}}
<p>No users available.</p>
{{end}}
with
{{with ...}} ... {{end}}
结构用于在模板中设置一个临时的上下文,使你能够在一段模板中访问该上下文中的字段或方法。
以下是有关 {{with ...}}
结构的详细说明:
-
{{with ...}} ... {{end}}
:with
结构允许你在其中设置一个新的上下文。这个新的上下文通常是一个字段或方法调用,如{{with .Field}}
或{{with .Method}}
。在with
结构内部,你可以使用点号 (.
) 来引用该新上下文,而不需要在每个字段或方法前使用点号。
with
结构在以下情况下非常有用:
-
链式访问:当你需要在模板中多次访问同一个字段或方法时,使用
with
可以减少冗余的点号 (.
)。 -
增强可读性:在模板中使用
with
可以增强可读性,使模板更具清晰性。
以下是一个示例,演示如何在模板中使用 {{with ...}}
结构:
{{with .User}}
<h1>Welcome, {{.Name}}!</h1>
<p>Email: {{.Email}}</p>
{{else}}
<p>Guest user</p>
{{end}}
比较函数
eq 如果arg1 == arg2则返回真
ne 如果arg1 != arg2则返回真
lt 如果arg1 < arg2则返回真
le 如果arg1 <= arg2则返回真
gt 如果arg1 > arg2则返回真
ge 如果arg1 >= arg2则返回真