go语言标准库之http/template
Posted zhaohaiyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言标准库之http/template相关的知识,希望对你有一定的参考价值。
html/template
包实现了数据驱动的模板,用于生成可对抗代码注入的安全HTML输出。它提供了和text/template
包相同的接口,Go语言中输出HTML的场景都应使用text/template
包。
模板
在基于MVC的Web架构中,我们通常需要在后端渲染一些数据到HTML文件中,从而实现动态的网页效果。
模板示例
通过将模板应用于一个数据结构(即该数据结构作为模板的参数)来执行,来获得输出。模板中的注释引用数据接口的元素(一般如结构体的字段或者字典的键)来控制执行过程和获取需要呈现的值。模板执行时会遍历结构并将指针表示为’.‘(称之为”dot”)指向运行过程中数据结构的当前位置的值。
用作模板的输入文本必须是utf-8编码的文本。”Action”—数据运算和控制单位—由”“和”“界定;在Action之外的所有文本都不做修改的拷贝到输出中。Action内部不能有换行,但注释可以有换行。
HTML文件代码如下:
<!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 .</p>
</body>
</html>
我们的HTTP server端代码如下:
// main.go
func sayHello(w http.ResponseWriter, r *http.Request)
// 解析指定文件生成模板对象
tmpl, err := template.ParseFiles("./hello.html")
if err != nil
fmt.Println("create template failed, err:", err)
return
// 利用给定数据渲染模板,并将结果写入w
tmpl.Execute(w, "沙河小王子")
func main()
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":9090", nil)
if err != nil
fmt.Println("HTTP server failed,err:", err)
return
模板语法
.
模板语法都包含在和
中间,其中
.
中的点表示当前对象。
当我们传入一个结构体对象时,我们可以根据.
来访问结构体的对应字段。例如:
// main.go
type UserInfo struct
Name string
Gender string
Age int
func sayHello(w http.ResponseWriter, r *http.Request)
// 解析指定文件生成模板对象
tmpl, err := template.ParseFiles("./hello.html")
if err != nil
fmt.Println("create template failed, err:", err)
return
// 利用给定数据渲染模板,并将结果写入w
user := UserInfo
Name: "小王子",
Gender: "男",
Age: 18,
tmpl.Execute(w, user)
HTML文件代码如下:
<!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>性别:.Gender</p>
<p>年龄:.Name</p>
</body>
</html>
同理,当我们传入的变量是map时,也可以在模板文件中通过.
根据key来取值。
注释
/* a comment */
注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。
pipeline
pipeline
是指产生数据的操作。比如.
、.Name
等。Go的模板语法中支持使用管道符号|
链接多个命令,用法和unix下的管道类似:|
前面的命令会将运算结果(或返回值)传递给后一个命令的最后一个位置。
注意:并不是只有使用了|
才是pipeline。Go的模板语法中,pipeline的
概念是传递数据,只要能产生数据的,都是pipeline
。
变量
Action里可以初始化一个变量来捕获管道的执行结果。初始化语法如下:
$variable := pipeline
其中$variable是变量的名字。声明变量的action不会产生任何输出。
条件判断
Go模板语法中的条件判断有以下几种:
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,则会执行T0。
with
with pipeline T1 end
如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot。
with pipeline T1 else T0 end
如果pipeline为empty,不改变dot并执行T0,否则dot设为pipeline的值并执行T1。
预定义函数
执行模板时,函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一般不在模板内定义函数,而是使用Funcs方法添加函数到模板里。
预定义的全局函数如下:
and
函数返回它的第一个empty参数或者最后一个参数;
就是说"and x y"等价于"if x then y else x";所有参数都会执行;
or
返回第一个非empty参数或者最后一个参数;
亦即"or x y"等价于"if x then x else y";所有参数都会执行;
not
返回它的单个参数的布尔值的否定
len
返回它的参数的整数类型长度
index
执行结果为第一个参数以剩下的参数为索引/键指向的值;
如"index x 1 2 3"返回x[1][2][3]的值;每个被索引的主体必须是数组、切片或者字典。
print
即fmt.Sprint
printf
即fmt.Sprintf
println
即fmt.Sprintln
html
返回其参数文本表示的HTML逸码等价表示。
urlquery
返回其参数文本表示的可嵌入URL查询的逸码等价表示。
js
返回其参数文本表示的javascript逸码等价表示。
call
执行结果是调用第一个参数的返回值,该参数必须是函数类型,其余参数作为调用该函数的参数;
如"call .X.Y 1 2"等价于go语言里的dot.X.Y(1, 2);
其中Y是函数类型的字段或者字典的值,或者其他类似情况;
call的第一个参数的执行结果必须是函数类型的值(和预定义函数如print明显不同);
该函数类型值必须有1到2个返回值,如果有2个则后一个必须是error接口类型;
如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用模板执行者该错误;
比较函数
布尔函数会将任何类型的零值视为假,其余视为真。
下面是定义为函数的二元比较运算的集合:
eq 如果arg1 == arg2则返回真
ne 如果arg1 != arg2则返回真
lt 如果arg1 < arg2则返回真
le 如果arg1 <= arg2则返回真
gt 如果arg1 > arg2则返回真
ge 如果arg1 >= arg2则返回真
为了简化多参数相等检测,eq(只有eq)可以接受2个或更多个参数,它会将第一个参数和其余参数依次比较,返回下式的结果:
eq arg1 arg2 arg3
比较函数只适用于基本类型(或重定义的基本类型,如”type Celsius float32”)。但是,整数和浮点数不能互相比较。
自定义函数
Go的模板支持自定义函数。
func sayHello(w http.ResponseWriter, r *http.Request)
htmlByte, err := ioutil.ReadFile("./hello.html")
if err != nil
fmt.Println("read html failed, err:", err)
return
// 自定义一个夸人的模板函数
kua := func(arg string) (string, error)
return arg + "真帅", nil
// 采用链式操作在Parse之前调用Funcs添加自定义的kua函数
tmpl, err := template.New("hello").Funcs(template.FuncMap"kua": kua).Parse(string(htmlByte))
if err != nil
fmt.Println("create template failed, err:", err)
return
user := UserInfo
Name: "小王子",
Gender: "男",
Age: 18,
// 使用user渲染模板,并将结果写入w
tmpl.Execute(w, user)
我们可以在模板文件hello.html
中使用我们自定义的kua
函数了。
kua .Name
嵌套template
我们可以在template中嵌套其他的template。这个template可以是单独的文件,也可以是通过define
定义的template。
举个例子: t.html文件内容如下:
<!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>tmpl test</title>
</head>
<body>
<h1>测试嵌套template语法</h1>
<hr>
template "ul.html"
<hr>
template "ol.html"
</body>
</html>
define "ol.html"
<h1>这是ol.html</h1>
<ol>
<li>吃饭</li>
<li>睡觉</li>
<li>打豆豆</li>
</ol>
end
ul.html文件内容如下:
<ul>
<li>注释</li>
<li>日志</li>
<li>测试</li>
</ul>
我们注册一个templDemo
路由处理函数.
http.HandleFunc("/tmpl", tmplDemo)
tmplDemo
函数的具体内容如下:
func tmplDemo(w http.ResponseWriter, r *http.Request)
tmpl, err := template.ParseFiles("./t.html", "./ul.html")
if err != nil
fmt.Println("create template failed, err:", err)
return
user := UserInfo
Name: "小王子",
Gender: "男",
Age: 18,
tmpl.Execute(w, user)
以上是关于go语言标准库之http/template的主要内容,如果未能解决你的问题,请参考以下文章