Action(动作)简介
Go 模板的动作就是一些嵌入到模板里面的命令,这些命令在模板中需要放到两个 大括号里{{ 动作 }},之前我们已经用过一个很重要的动作:点(.),它代表了传递给模板的数据。
以下是Go语言官方给出的action列表,其中"Arguments"和"pipelines"代表数据的执行结果
{{/* a comment */}}
注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止,就像这里表示的一样。
{{pipeline}}
pipeline的值的默认文本表示会被拷贝到输出里。
{{if pipeline}} T1 {{end}}
如果pipeline的值为empty,不产生输出,否则输出T1执行结果。不改变dot的值。
Empty值包括false、0、任意nil指针或者nil接口,任意长度为0的数组、切片、字典。
{{if pipeline}} T1 {{else}} T0 {{end}}
如果pipeline的值为empty,输出T0执行结果,否则输出T1执行结果。不改变dot的值。
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
用于简化if-else链条,else action可以直接包含另一个if;等价于:
{{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
{{range pipeline}} T1 {{end}}
pipeline的值必须是数组、切片、字典或者通道。
如果pipeline的值其长度为0,不会有任何输出;
否则dot依次设为数组、切片、字典或者通道的每一个成员元素并执行T1;
如果pipeline的值为字典,且键可排序的基本类型,元素也会按键的顺序排序。
{{range pipeline}} T1 {{else}} T0 {{end}}
pipeline的值必须是数组、切片、字典或者通道。
如果pipeline的值其长度为0,不改变dot的值并执行T0;否则会修改dot并执行T1。
{{template "name"}}
执行名为name的模板,提供给模板的参数为nil,如模板不存在输出为""
{{template "name" pipeline}}
执行名为name的模板,提供给模板的参数为pipeline的值。
{{with pipeline}} T1 {{end}}
如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot。
{{with pipeline}} T1 {{else}} T0 {{end}}
如果pipeline为empty,不改变dot并执行T0,否则dot设为pipeline的值并执行T1。
action作用:action可以完成流程控制、循环、模版等操作.通过使用action可以在模版中完成简单逻辑处理(复杂逻辑处理应该在go中实现,传递给模版的数据应该是已经加工完的数据)
接下来通过实例来介绍几个常用的动作。
1.条件动作
条件动作非常常用,通过判断是否满足条件就可以执行相应的动作。
1.1格式:
条件动作有两种格式可以实现条件动作。
格式一:
{{ if arg}}
要显示的内容
{{ end }}
格式二:
{{ if arg}}
要显示的内容
{{else}}
当 if 条件不满足时要显示的内容
{{ end }}
上述格式中的 arg 是传递给条件动作的参数,该值可以是一个字符串常量、 一个变量、一个返回单个值的函数获取方法等。
1.2举例
网页代码:
<html>
<head>
<title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body>
<!-- 嵌入动作 -->
{{if .}}
可以提交笔记了
{{else}}
你的笔记还没写好
{{end}}
</body>
</html>
处理器代码:
func handler(w http.ResponseWriter, r *http.Request) {
//解析模板文件
t := template.Must(template.ParseFiles("hello.html"))
//声明一个变量
age := true
//执行模板
t.Execute(w, age)
}
2.迭代动作
迭代动作可以对数组、切片、映射或者通道进行迭代。
2.1格式
格式一:
{{range . }}
遍历到的元素是 {{ . }}
{{ end }}
格式二:
{{range . }}
遍历到的元素是 {{ . }}
{{ else }}
没有任何元素
{{ end }}
格式中,range 后面的点代表被遍历的元素;要显示的内容里面的点代表遍历 到的元素。
2.2举例
网页端代码
<html>
<head>
<title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body>
<!-- 嵌入动作 -->
{{range .}}
<a href="#">{{.}}</a>
{{else}}
没有遍历到任何内容
{{end}}
</body>
</html>
处理器代码:
func handler(w http.ResponseWriter, r *http.Request) {
//解析模板文件
t := template.Must(template.ParseFiles("hello.html"))
//声明一个字符串切片
stars := []string{"李大", "李二", "李狗蛋"}
//执行模板
t.Execute(w, stars)
}
2.3说明
- 如果迭代之后是一个个的结构体,获取结构体中的字段值使用 .字段名 方式获取
{{range . }}
获取结构体的 Name 字段名 {{ .Name }}
{{ end }}
- 迭代 Map 时可以设置变量,变量以$开头:
{{ range $k , $v := . }}
键是 {{ $k }} , 值是 {{ $v }}
{{ end }}
- 迭代管道
{{ c1 | c2 | c3 }}
c1、c2 和 c3 可以是参数或者函数。管道允许用户将一个参数的输出 传递给下一个参数,各个参数之间使用 | 分割。
3.设置动作
3.1格式
格式一
{{ with arg }}
为传过来的数据设置的新值是{{ . }}
{{ end }}
arg就是给传过来的数据设置的新值
格式二
{{ with "" }}
由于with后面是空串,此部分不执行,执行else的部门,相当于没有修改传过来的数据
{{ else }}
传过来的数据仍然是{{ . }}
{{ end }}
3.2举例
网页端代码:
<html>
<head><title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body> <!-- 嵌入动作 -->
<div>得到的数据是:{{.}}</div>
{{with "太子"}}
<div>替换之后的数据是:{{.}}</div>
{{end}}
<hr/>
{{with ""}}
<div>看一下现在的数据是:{{.}}</div>
{{else}}
<div>数据没有被替换,还是:{{.}}</div>
{{end}}
</body>
</html>
处理器代码:
func handler(w http.ResponseWriter, r *http.Request) {
//解析模板文件
t := template.Must(template.ParseFiles("hello.html"))
//执行模板
t.Execute(w, "狸猫")
}
4.包含动作
包含动作允许用户在一个模板里包含另一个模板
4.1格式
格式一
不将数据传入到包含的模板中
{{ template “name” }}
name是被包含的模板的名字
格式二
将传过来的数据再传入到包含的模板中
{{ template “name” .}}
动作中的 . 就是要传给被包含模板的数据,也是后台传给当前模板的数据
4.2举例
网页端代码1:
<html>
<head><title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body> <!-- 嵌入动作 -->
<div>从后台得到的数据是:{{.}}</div> <!-- 包含 hello2.html 模板 --> {{ template "hello2.html"}}
<div>hello.html 文件内容结束</div>
<hr/>
<div>将 hello.html 模板文件中的数据传递给 hello2.html 模 板文件</div>
{{ template "hello2.html" . }}
</body>
</html>
网页端代码2:
<html>
<head><title>hello2 模板文件</title>
<meta charset="utf-8"/>
</head>
<body> <!-- 嵌入动作 -->
<div>hello2.html 模板文件中的数据是:{{.}}</div>
</body>
</html>
处理器代码:
func handler(w http.ResponseWriter, r *http.Request) {
//解析模板文件
t := template.Must(template.ParseFiles("hello.html", "hello2.html"))
//执行模板
t.Execute(w, "测试包含")
}
5.定义动作
当我们访问一些网站时,经常会看到好多网页中有相同的部分:比如导航栏、版权 信息、联系方式等。这些相同的布局我们可以通过定义动作在模板文件中定义模板来实 现。定义模板的格式是:以{{ define “layout” }}开头,以{{ end }}结尾。
对于每个页面中的相同部门,例如导航栏、版权信息等可以通过定义动作在模板文件中定义模板来实现
5.1格式
{{ define "arg" }}
这里就是页面中相同的部门
{{ end }}
arg就是定义的模板的名字,将来可以在其他模板文件中通过包含动作将当前定义的模板包含进去
我们还可以在不同的模板文件中定义同名的模板
5.2举例
先在一个模板文件(hello.html)中定义一个模板
<!-- 定义模板 --> {{ define "model"}}
<html>
<head><title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body> {{ template "content"}}</body>
</html> {{ end }}
然后在一个模板文件中定义多个模板
<!-- 定义模板 --> {{ define "model"}}
<html>
<head><title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body> {{ template "content"}}</body>
</html> {{ end }}
{{ define "content"}}
<a href="#">点我有惊喜</a>
{{ end }}
处理器代码:
func handler(w http.ResponseWriter, r *http.Request) {
//解析模板文件
t := template.Must(template.ParseFiles("hello.html"))
//执行模板
t.ExecuteTemplate(w, "model", "")
}
6.块动作
块动作相当于定义了一个默认的模板,在找不到模板时将会使用它
6.1格式
```lua
{{ block arg .}}
如果在模板文件中找不到名字叫arg的模板时就执行当前的内容
{{ end }}
6.2举例
网页端代码:
<!-- 定义模板 --> {{ define "model"}}
<html>
<head><title>模板文件</title>
<meta charset="utf-8"/>
</head>
<body> {{ block "content" .}}如果找不到就显示我 {{ end }}</body>
</html> {{ end }}
处理器端代码:
func handler(w http.ResponseWriter, r *http.Request) {
rand.Seed(time.Now().Unix())
var t *template.Template
if rand.Intn(5) > 2 {
//解析模板文件
t = template.Must(template.ParseFiles("hello.html", "content1.html"))
} else {
//解析模板文件
t = template.Must(template.ParseFiles("hello.html"))
}
//执行模板
t.ExecuteTemplate(w, "model", "")
}