Go Web 学习笔记(五)模版引擎


Go Web 模版引擎

模版引擎使用

Go Web 中的模版引擎可以将一个已经写好的 HTML 文件以及相应的数据渲染好之后返回给客户端,需要用到 html/template 包(该包是 text/template 包的安全版本)。

使用 Go Web 模版引擎需要以下两个步骤:

1、对文本格式的模版进行语法分析,创建一个经过语法分析的模版结构,其中模版源既可以是一个字符串,也可以是模版文件中包含的内容。

2、执行经过语法分析的模版,将 ResponseWriter 和模版所需的 动态数据 传递给模版引擎,被调用的模版引擎会把经过语法分析的模版和传入的数据结合起来,生成出最终的 HTML,并将这些 HTML 传递给ResponseWriter。

一个简单的使用案例:

package main

import (
	"html/template"
	"net/http"
)

func main() {
	http.HandleFunc("/testtemplate", handler)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	// 解析模版文件(注意模版文件的路径信息,当前项目的路径为根路径)
	//t, _ := template.ParseFiles("./template/index.html")
	// 通过Must函数来让Go自动处理异常
	t := template.Must(template.ParseFiles("./template/index.html"))
	// 执行模版文件
	t.Execute(w, "hello Template")
	// 将响应数据指定在index2.html中显示(可以一次加载多个模版文件然后使用该方法指定模版引擎)
	//t.ExecuteTemplate(w, "index2.html", "index2.html")
}

模版引擎动作

其中在执行模版文件的过程中需要向模版文件中传递执行的数据,此时就需要使用模版文件中的 action(动作)

Go 模版的动作就是一些嵌入到模版里面的命令,这些命令在模版中需要放到两个大括号里面 {{}},例如:

\{\{.\}\} // 传递给模版的数据
\{\{/* a comment */\}\} // 模版中的注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止,就像这里表示的一样。

接下来介绍一些常见的模版动作

条件动作

条件动作可以对 bool 类型的变量进行判断从而显示指定的内容:

// 简单if,其中的 arg 是传递给条件动作的参数,该值可以是一个字符串常量、一个变量、一个返回单个值的函数获取方法等。
\{\{if arg\}\}
要显示的内容
\{\{end\}\}

// if-else
\{\{if arg\}\}
要现实的内容
\{\{else\}\}
if条件不满足时显示的内容
\{\{end\}\}

示例:

处理器设置:

// TestIf 条件动作测试
func TestIf(w http.ResponseWriter, r *http.Request) {
	t := template.Must(template.ParseFiles("./action/if.html"))
	age := 17
	if age >= 18 {
		t.Execute(w, true)
	} else {
		t.Execute(w, false)
	}
}

页面显示:

\{\{if .\}\}
<div>已满十八岁</div>
\{\{else\}\}
<div>未满十八岁</div>
\{\{end\}\}

这样页面显示的内容为:未满十八岁

迭代动作

迭代动作可以对数组、切片、映射或者通道进行迭代:

// 迭代方式一,range后面的点代表未被遍历的元素,要显示的内容里面的点代表的是遍历到的元素
\{\{range .\}\}
遍历到的元素是 \{\{.\}\}
\{\{end\}\}

// 迭代方式二:
\{\{range .\}\}
遍历到的元素是 
\{\{else\}\}
没有任何元素
\{\{end\}\}

// 迭代map的时候可以设置变量,变量以 $ 开头
\{\{range $k,$v := .\}\}
键是:\{\{$k\}\} 值是:\{\{$v\}\}
\{\{end\}\}

// 迭代管道
// c1、c2、c3可以是参数或者函数,管道允许用户将一个参数的输出传递给下一个参数,各个参数之间使用 | 分割
\{\{c1|c2|c3\}\}

示例:

处理器设置:

// TestRange 迭代动作测试
func TestRange(w http.ResponseWriter, r *http.Request) {
	t := template.Must(template.ParseFiles("./action/range.html"))
	data := []string{"苹果", "西瓜", "香蕉", "橘子"}
	t.Execute(w, data)
}

界面显示:

当前的水果有:<br>
<ul>
    \{\{range .\}\}
        <li>\{\{.\}\}</li>
    \{\{end\}\}
</ul>

设置动作

设置动作允许在指定的范围内对点(.)设置值

// 格式一
\{\{with arg\}\}
传递过来的数据设置的新值为:\{\{.\}\}
\{\{end\}\}

// 格式二
// with "" 表示没有修改,则会执行 else 中的内容
\{\{with arg\}\}
传递过来的数据设置的新值为:\{\{.\}\}
\{\{else\}\}
传递过来的数据仍然是:\{\{.\}\}
\{\{end\}\}

包含动作

包含动作允许用户在一个模版里面包含另一个模版,从而构建嵌套的模版:

// 格式一,name为被包含的模版的名字(字符串类型)
\{\{template "模版名"\}\}

// 格式二,arg是用户想要传递给被嵌套模版的数据
\{\{template "模版名" arg\}\}

定义动作

网页中经常有很多重用的部分:导航栏、版本信息、联系方式等。这些相同的布局可以通过定义动作在模版文件中定义模版来实现。

定义模版的格式是:

\{\{define "模版名"\}\}
模版内容
\{\{end\}\}

在定义的模版中可以使用包含动作(template)来包含其他已经定义好的模版

在html文件中定义好模版之后处理器中需要执行模版的使用就得使用ExecuteTemplate方法,其中传入定义好的模版的名字以及所要传递的数据。

在不同的模版文件中定义同名的模版文件时,需要在处理器中加载模版的时候选择指定的模版(利用一次加载多个模版来实现)。

示例:

处理器设置:

// TestTemplate 包含动作测试
func TestTemplate(w http.ResponseWriter, r *http.Request) {
	t := template.Must(template.ParseFiles("./action/template.html"))
	t.Execute(w, "")
}

页面显示:

\{\{define "content"\}\}
<b>这里显示的是content模版的内容</b>
\{\{end\}\}
<div>开始显示本页面的内容</div>
\{\{template "content"\}\}

块动作

Go 1.6 引入了一个新的块动作。这个动作允许用户定义一个模版并立即使用,相当于设置了一个默认的模版。

\{\{block "模块名" .\}\}
默认显示该内容
\{\{end\}\}