简单使用
要使用模板需要分三个步骤,分别是定义、解析和渲染,下面咱一步一步来
- 定义
创建一个.tmpl
或是.tpl
文件,在goland中第一次创建这种类型的文件他会让你选用什么文件的格式去提示这类文件,这时候选择 go template files。
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>测试</title> </head> <body> {{ . }}<br> {{ .name}}<br> {{ .sex}} </body> </html>
其中{{ }} 是模板里的标识符,该标识符可能会与Vue中某些代码冲突,后面会提供修改默认标识符的方法,在表示符中的
.
代表着数据,这个数据是从后台传来的。
- 解析
t, err := template.ParseFiles("./test.tmpl")
将刚才定义的模板文件解析到程序中,上方调用的方法是解析多个文件
- 解析方法
// 解析多个文件 func ParseFiles(filenames ...string) (*Template, error) { return parseFiles(nil, readFileOS, filenames...) } // 通过正则表达式解析多个文件 func ParseGlob(pattern string) (*Template, error) { return parseGlob(nil, pattern) } // 类似于上面两种方法,但是是从文件系统fs读取,而不是主机操作系统的文件系统。 func ParseFS(fs fs.FS, patterns ...string) (*Template, error) { return parseFS(nil, fs, patterns) }
- 渲染
mp := map[string]interface{}{ "name": "张三", "sex": "男", } err = t.Execute(w, mp)
将数据渲染到刚解析的模板中
// 可以看出这个data是个空接口类型,也就意味着是什么值都可以传的 func (t *Template) Execute(wr io.Writer, data interface{}) error { if err := t.escape(); err != nil { return err } return t.text.Execute(wr, data) }
- 另外一种渲染方法,指定模板文件进行渲染,适用于有好多解析文件在一起时使用
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { tmpl, err := t.lookupAndEscapeTemplate(name) if err != nil { return err } return tmpl.text.Execute(wr, data) }
package main import ( "fmt" "html/template" "net/http" ) func sayHello(w http.ResponseWriter,r *http.Request) { t, err := template.ParseFiles("./test.tmpl") if err != nil { fmt.Printf("parse file failed err := %v",err) } mp := map[string]interface{}{ "name": "张三", "sex": "男", } err = t.Execute(w, mp) if err != nil { fmt.Printf("execute file failed err := %v",err) } } func main() { http.HandleFunc("/",sayHello) err := http.ListenAndServe(":9000", nil) if err != nil { fmt.Printf("listen address failed err = %v",err) } }
- 注释
注释使用的符号为{{/* */}},支持多行注释,如
{{/* 注释内容 */}}
{{ $obj := 数据 }}
- 声明变量之后就可以在模板文件中使用了。
例子:
test.tmpl
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>变量使用</title> </head> <body> MSG :{{ . }}<br> 姓名 :{{ .Name }}<br> 性别 : {{ .Sex }}<br> {{/* 使用变量 */}} <div> {{ $num := "123" }} 年岁 :{{ $num }} </div> </body> </html>
package main import ( "fmt" "html/template" "net/http" ) func sayHello(w http.ResponseWriter,r *http.Request) { t, err := template.ParseFiles("./test.tmpl") if err != nil { fmt.Printf("parse file failed err := %v",err) } err = t.Execute(w, struct { Name string Sex string }{ Name: "张三", Sex: "女", }) if err != nil { fmt.Printf("execute file failed err := %v",err) } } func main() { http.HandleFunc("/",sayHello) err := http.ListenAndServe(":9000", nil) if err != nil { fmt.Printf("listen address failed err = %v",err) } }
这里要注意一点,就是当传给模板的数据为结构体时,根据go语言的特性,属性名小写的属性外界将获取不到值。
判断与清楚空白符操作
判断
在模板中的判断语句写法同go语言类似
{{ if [比较函数] 变量 [比较对象] }} 如果为真要执行的语句 {{ end }}
如果是只有变量的话,就判断变量是否存在值,如果存在就执行。
也可以使用 if … else … 语句,或if … else if … 语句,如
{{ if [比较函数] 变量 [比较对象] }} {{ else }} {{ end }}
{{ if [比较函数] 变量 [比较对象] }} {{ else if [比较函数] 变量 [比较对象]}} {{ end }}
去空白字符
使用
清楚变量左右两侧的空白符号,当然也可以只清除一侧,只需要将不需要清除的一侧的 - 舍去 {{- -}}
例子:
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>判断与清楚空白符操作</title> </head> <body> MSG :{{ . }}<br> 姓名 :{{ .Name }}<br> 性别 : {{ .Sex }}<br> {{ $num := .Age }} 年龄 :{{ $num }} {{/* 判断使用 注意,要先写条件之后跟上比较对象*/}} {{/* 比较函数 eq == eq可以进行多个值比较 如 eq n1 n2 n3 ,就会拿n1 分别跟n2,n3比较 ne != lt < le <= gt > ge >= */}} <div> {{ if lt $num 18 }} 好好吃饭 {{ else if ge $num 18 }} 别在熬夜了 {{end}} </div> {{/* {{- -}} 取出空白符的符号使用*/}} {{ $num }} = {{ $num }}<br> {{/* 取出空白符,让左侧或右侧能与其他的文本贴贴*/}} {{ $num -}} = {{- $num }} </body> </html>
package main import ( "fmt" "html/template" "net/http" "os" "path/filepath" ) func sayHello(w http.ResponseWriter,r *http.Request) { // ./ 代表项目路径 t, err := template.ParseFiles("./test.tmpl") if err != nil { fmt.Printf("parse file failed err := %v",err) } err = t.Execute(w, struct { Name string Sex string Age int }{ Name: " 张三 ", Sex: "女", Age: 20, }) if err != nil { fmt.Printf("execute file failed err := %v",err) } } func main() { http.HandleFunc("/",sayHello) root := filepath.Dir(os.Args[0]) fmt.Println(root) err := http.ListenAndServe(":9000", nil) if err != nil { fmt.Printf("listen address failed err = %v",err) } }
循环、with和与预定义函数的使用
循环
使用range
关键字进行遍历
这个变量只能是数组、切片、map或者通道 {{ range 变量 }} {{ end }}
{{ range $index,$valuse = 变量 }} {{ end }}
在range
中也可以使用else语句,如果所遍历的这个变量长度为0,则执行else语句
{{ range 变量 }} {{ else }} {{ end }}
with
with
的作用为重新定义 .
所代表的数据,这个重新定义有一个范围,只有在范围内 .
才代表with
重新定义的那个数据
{{ with 变量 }} 在这中间 . 都将被替换为变量的数据 {{ end }}
当赋值的变量为空时,可以使用 else 语句来检测 .
有没有被重新赋值
{{ with 变量 }} {{ else }} 如果变量为空则执行这里的语句 {{ end }}
预定义函数
模板中的预定义函数有:
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。 这个函数在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,模板执行会中断并返回给调用模板执行者该错误;
例子:
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>循环,with和预定义函数的使用</title> </head> <body> {{/* 循环 */}} {{ range $index,$v1 := . }} 下标:{{ $index }} 姓名:{{ $v1 }} <br> {{ end }} <hr> {{/* with 更改点的值*/}} 开始时:{{ . }}<br> {{ with "斗地主研讨会"}} 转换后:{{ . }} {{ end }} <hr> {{/* 预定义函数 */}} {{/* 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。 这个函数在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,模板执行会中断并返回给调用模板执行者该错误; */}} 研讨会人数:{{ len . }} </body> </html>
package main import ( "fmt" "html/template" "net/http" "os" "path/filepath" ) func sayHello(w http.ResponseWriter,r *http.Request) { // ./ 代表项目路径 t, err := template.ParseFiles("./test.tmpl") if err != nil { fmt.Printf("parse file failed err := %v",err) } strings := []string{"张安","潘凤","李翔"} err = t.Execute(w,strings) if err != nil { fmt.Printf("execute file failed err := %v",err) } } func main() { http.HandleFunc("/",sayHello) root := filepath.Dir(os.Args[0]) fmt.Println(root) err := http.ListenAndServe(":9000", nil) if err != nil { fmt.Printf("listen address failed err = %v",err) } }