Template模板
模板语法
{{.}}
模板语法都包含在{{
和}}
中间,其中{{.}}
中的点表示当前对象。
当我们传入一个结构体对象时,我们可以根据.
来访问结构体的对应字段。例如:
func welcome(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("html/view/index.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
type User struct {
Name string
Age int
}
user := User{Name: "Tim", Age: 18}
tmpl.Execute(w, user)
}
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("html/static"))))
server := http.Server{Addr: ":8080"}
http.HandleFunc("/", welcome)
server.ListenAndServe()
}
<!DOCTYPE html>
<html lang="en">
<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</title>
</head>
<body>
<p>Hello {{.Name}}</p>
<p>年龄:{{.Age}}</p>
</body>
</html>
Pipeline
- 组成:
- 命令(Command):
- 命令可以是一个简单的值(如变量或常量)、函数调用、方法调用等
- 例如:
{{.Name}}
、{{ToUpper "hello"}}
- 管道符号(|):
- 管道符号用于将前一个命令的输出传递给下一个命令作为输入
- 例如:
{{.Name | ToUpper}}
- 链式操作:
- Pipeline 支持链式操作,多个命令可以通过管道符号连接在一起
- 例如:
{{.Name | ToUpper | printf "%s"}}
- 工作原理:
- 每个命令的输出会作为下一个命令的最后一个参数
- 如果某个命令返回了多个值(例如,一个函数返回值和错误),只有第一个值会被传递给下一个命令
- 如果某个命令返回了错误,整个 pipeline 的执行会停止,并返回错误
变量
$n := 1000
条件判断
if
{{if pipeline}}
T1
{{end}}
{{if pipeline}}
T1
{{else}}
T0
{{end}}
{{if pipeline}}
T1
{{else if pipeline}}
T0
{{end}}
range
Go的模板语法中使用range关键字进行遍历,有以下两种写法,其中pipeline的值必须是数组、切片、字典或者通道
{{range pipeline}}
T1
{{end}}
如果pipeline的值其长度为0,不会有任何输出
{{range pipeline}}
T1
{{else}}
T0
{{end}}
如果pipeline的值其长度为0,则会执行else代码
with
{{with pipeline}}
T1
{{end}}
如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot
{{with pipeline}}
T1
{{else}}
T0
{{end}}
如果pipeline为empty,不改变dot并执行else,否则dot设为pipeline的值并执行T1
预定义函数
函数名 | 功能描述 | 示例 |
---|---|---|
and | 函数返回它的第一个空参数或者最后一个参数。即and x y 等价于if x then y else x 。所有参数都会执行 | {{and .X .Y}} |
or | 返回第一个非空参数或者最后一个参数。or x y 等价于if x then x else y 。所有参数都会执行 | {{or .X .Y}} |
not | 返回单个参数的布尔值的否定 | {{not .X}} |
len | 返回参数的整数类型长度 | {{len .Slice}} |
index | 执行结果为第一个参数以剩下的参数为索引/键指向的值 | {{index .X 1 2 3}} |
等效于fmt.Sprint | {{print .X}} | |
printf | 等效于fmt.Sprintf | {{printf “Name: %s” .Name}} |
println | 等效于fmt.Sprintln | {{println .X}} |
html | 返回参数文本表示的 HTML 逸码等价表示 | {{html .X}} |
urlquery | 返回参数文本表示的可嵌入 URL 查询的逸码等价表示 | {{urlquery .X}} |
js | 返回参数文本表示的 JavaScript 逸码等价表示 | {{js .X}} |
call | 执行结果是调用第一个参数的返回值,第一个参数必须是函数类型 | {{call .X.Y 1 2}} |
比较函数
函数 | 描述 | 适用性 |
---|---|---|
eq | 如果 arg1 == arg2 则返回真 | 仅适用于基本类型(或重定义的基本类型,例如 type Celsius float32 )。整数和浮点数不能互相比较。 |
特殊情况:eq 可以接受 2 个或更多参数。它会将第一个参数依次与其余参数进行比较。 | 例如:eq arg1 arg2 arg3 会检查 arg1 == arg2 且 arg1 == arg3 。 | |
ne | 如果 arg1 != arg2 则返回真 | 与 eq 同样的限制。 |
lt | 如果 arg1 < arg2 则返回真 | 仅适用于可比较的基本类型。 |
le | 如果 arg1 <= arg2 则返回真 | 仅适用于可比较的基本类型。 |
gt | 如果 arg1 > arg2 则返回真 | 仅适用于可比较的基本类型。 |
ge | 如果 arg1 >= arg2 则返回真 | 仅适用于可比较的基本类型。 |
重要说明
- 可比较性:比较函数(包括
eq
)仅适用于基本类型。- 类型限制:整数和浮点数不能直接互相比较。
- 多参数支持:仅
eq
函数支持多个参数,用于同时与多个后续参数进行相等性检查。
自定义函数
func add(a, b int) (ans int) {
ans = a + b
return
}
func welcome(w http.ResponseWriter, r *http.Request) {
// 创建模板并注册自定义函数
funcMap := template.FuncMap{"add": add}
tmpl := template.New("index.html").Funcs(funcMap)
tmpl, err := tmpl.ParseFiles("index.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl.Execute(w, nil)
}
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("html/static"))))
server := http.Server{Addr: ":8080"}
http.HandleFunc("/", welcome)
server.ListenAndServe()
}
{{add arg1 arg2}}
嵌套template
go:
func welcome(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("./index.html", "./head.html", "./foot.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl.Execute(w, nil)
// 在ExecuteTemplate中,如果html代码中使用define定义了新名称,就不能再使用文件名作为参数
//tmpl.ExecuteTemplate(w, "index.html", nil)
}
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("html/static"))))
server := http.Server{Addr: ":8080"}
http.HandleFunc("/", welcome)
server.ListenAndServe()
}
Execute和ExecuteTemplate的区别:
- Execute渲染主模板,一般默认是第一个
- ExecuteTemplate可以指定渲染的模板名称(文件路径)
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
<script type = "text/javascript" src = "../static/js/index.js"></script>
</head>
<body>
{{template "head" "这里是index.html的head部分"}}
<h1>这里是index.html的body部分</h1>
{{template "foot" "这里是index.html的foot部分"}}
</body>
</html>
{{define "head"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>head</title>
</head>
<body>
head.html
{{.}}
</body>
</html>
{{end}}
{{define "foot"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>foot</title>
</head>
<body>
foot.html
{{.}}
</body>
</html>
{{end}}
define
可以创建一个可在其他地方调用的子模板若你已经通过
define
定义了一个子模板名,那么在调用时必须使用该名称