Go语言标准库之htmltemplate详解

Go语言标准库之htmltemplate详解,第1张

Go语言标准库之html/template

html/template包实现了数据驱动的模板,用于生成可防止代码注入的安全的HTML内容。
它提供了和text/template包相同的接口,Go语言中输出HTML的场景都应使用html/template这个包。

官方文档里面也给了详细的解释哈,有兴趣可以看看哈。 模板引擎的使用 我们用这个一般三步走,定义、解析、渲染

定义模板文件

这个定义一个html文件即可,后缀名成可以设定为 tmpl 或者 tpl ,不过我们一般使用 tmpl 作为模板文件后缀。

模板文件解析

上面定义好了模板文件之后,可以使用下面的常用方法去解析模板文件,得到模板对象:
func (t *Template) Parse(src string) (*Template, error)
func ParseFiles(filenames ...string) (*Template, error)
func ParseGlob(pattern string) (*Template, error)
三种方式都可以实现,待会我们来举个简单的例子试试

模板渲染

func (t *Template) Execute(wr io.Writer, data interface{}) error
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
我们通过execute函数把数据放入到模板文件里面去 模板语法

这里我们要说一下这个模板的语法哈。

模板语法都包含在 {{和}} 中间,其中 {{.}} 中的点表示当前对象。

{{.}} ,里面的这个点,就是传入的对象。例如:
	name := "张三"
	err = t.Execute(w,name)
这样子, 括号里面的点就表示张三。可以直接放入到模板文件里面去动态的显示。这里面的模板类似于Java里面的Thymeleaf,只不过语法不一样

当然,除了基本类型,还可以设置结构体,或者map。来看看结构体的

	u1 := User{
		Name:"小公主",
		Gender:"女",
		Age:16,
	}
	err = t.Execute(w,u1)
这样也可以,取数据的时候通过 .Name .Age .Gender 的形式进行读取数据即可这个主意要首字母大写哈,因为结构体要对外开放权限哦

然后我们来看看map,来做个完整的例子吧

package main
import (
	"fmt"
	"html/template"
	"net/http"
)
type User struct {
	Name string
	Gender string
	Age int
}
func index(w http.ResponseWriter, r *http.Request)  {
	// 解析模板
	t, err := template.ParseFiles("Template_test/index.tmpl")
	if err != nil {
		fmt.Println("Parse template failed! err:",err)
		return
	}
	// 渲染模板
	u1 := User{
		Name:"小公主",
		Gender:"女",
		Age:16,
	}
	m1 := map[string]interface{}{
		"name":"小皇子",
		"gender":"男",
		"age" : 18,
	}
	err = t.Execute(w,map[string]interface{}{
		"u1":u1,
		"m1":m1,
	})
	if err != nil {
		fmt.Println("render template failed,err : ",err)
		return
	}
}
func main() {
	http.HandleFunc("/index",index)
	err := http.ListenAndServe(":9090",nil)
	if err != nil {
		fmt.Println("HTTP server start failed! err : ", err)
		return
	}
}

这里我们可以看到哈,我们将一个map数据和一个结构体数据统一的放入到一个map里面,然后将这个全部的数据统一的返回给模板。这个稍微比Java麻烦一点哈,一次只能返回一个大的map,啊哈哈哈哈哈不过问题也不大。然后我们来看看模板

我们可以看到哈,模板的引用也是非常的简单。值得一说的是要注意大小写哈,map里面的因为直接就是key/value的形式,所以不用首字母大写。然后我们来看看效果。

完美实现哈,现在我们就学会了数据的引用和传输了。 模板的注释 {{/* 需要注释的内容 */}}注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止。我最讨厌的就是不写注释的同学了,啊哈哈哈哈哈 pipeline

pipeline是指产生数据的 *** 作。比如{{.}}、{{.Name}}等。Go的模板语法中支持使用管道符号|链接多个命令,用法和unix下的管道类似:|前面的命令会将运算结果(或返回值)传递给后一个命令的最后一个位置。

并不是只有使用了|才是pipeline。Go的模板语法中,pipeline的概念是传递数据,只要能产生数据的,都是pipeline。 变量

语法就是这样子哈,还是方便的。 移除空格 就是跟trim函数差不多,去除前后的空格
{{- .Name -}}

注意:- 要紧挨{{和}},同时与模板值之间需要使用空格分隔。

条件判断语句 Go模板语法中的条件判断有以下几种:
{{if pipeline}} T1 {{end}}

{{if pipeline}} T1 {{else}} T0 {{end}}

{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
我们来简单演示一下

这里我们比较一下两个参数的,i是否小于 200 ,lt是小于的意思哈,后面会说

结果就是这样哈,这就是if了,也是可以进行嵌套的哈,感兴趣的话,可以自己去尝试哈。 range循环遍历 这个就是将数据进行一个循环遍历输出的了,相当于for循环的样子Go的模板语法中使用range关键字进行遍历,有以下两种写法,其中pipeline的值必须是数组切片字典或者通道

举个例子:

	hobbyList := []string{
		"篮球",
		"足球",
		"双色球",
	}
我们将这个切片通过Execute函数传到模板上面去。然后对这个切片进行遍历输出

这里我们声明两个变量,分别来接受这个切片的索引和内容

展示效果,还行哈,css这块大家有兴趣自己去配置哈。

看下range的全部语法哈

{{range pipeline}} T1 {{end}}
如果pipeline的值其长度为0,不会有任何输出

{{range pipeline}} T1 {{else}} T0 {{end}}
如果pipeline的值其长度为0,则会执行T0。
with 帮忙省东西的,比如,前面我们写 .u1 和 .m1 这种,我们可以通过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和println同理
html返回与其参数的文本表示形式等效的转义HTML。
这个函数在html/template中不可用。
urlquery以适合嵌入到网址查询中的形式返回其参数的文本表示的转义值。
这个函数在html/template中不可用。
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则返回真
用法跟上面的类似哈

返回的是布尔类型的数值哈,返回值如下: 例如false 或者 true

学完这些,感觉在面向数据动态绑定的时候,应该可以解决大部分的web方面的难点了。啊哈哈哈哈哈哈

这些只是预处理好的函数,但是呢,我们在实际开发中,所需要的函数是超级超级多的,那么我们就必须自己去建立函数拉,这个也是我们Template里面的重点要求掌握的哈!

自定义函数 我们来举个例子

这个时候就要分四步啦
1. 先我们定义一个函数类型的变量,里面写好函数
2. 然后获取模板对象,然后在这个对象里面进行注册函数,一定要在解析模板之前进行注册
3. 解析模板
4. 渲染模板

这就完成了一个自定义函数了,我们随便搞个函数,就问下别人吃了吗?
调用也是很方便的!!

因为我们在通过FuncMap进行注册的时候,取名叫wen,所以我们直接wen + 一个spring类型的变量即可。这就是自定义哈,很简单吧。

好了,进行学习就到这里拉,大家也要加油哦!

加油!!!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存