Golang | 模板
Contents
什么是模板
Go中模板处理通过包:
text/template和html/template完成
一个模板就是一个字符串或一个文件,里面包含了一个或多个双花括号 {{}} 包含的对象
Go中模板解析
Go中模板解析主要步骤:
- 创建模板对象
- 加载模板字串(或模板文件)
- 执行渲染模板
Note: 其中最后一步就是将加载的字符和数据进行格式化
基本用法
- 模板标签: 标签用 {{}}括起来
- 模板注释: 注释用 {{/* a comment */}}括起来表示注释内容
变量
Go渲染 template 的时候,接收一个 interface{} 类型的变量, 我们在模板文件或模板字串中取变量值然后渲染到模板里
模板渲染时 interface{} 接收的变量通常为:
- struct: 在模板中用struct的字段进行渲染
- map[string][interface{}: 在模板中使用key进行渲染
Usage:
- {{}}: 表示模板渲染时需要被替换的字段
- {{.}}: 表示输出当前对象的值
- {{.FieldOrMethodName}}: 表示输出struct对象的字段或方法名称为’FieldOrMethodName’的值- 注:要访问的对象必须可导出的
- 当 FieldOrMethodName 为匿名字段时, 可访问其内部字段或方法, 如 “New”: {{.FieldOrMethodName.New}}
- 当 New 是一个方法并返回一个struct对象,同样也可以访问其字段或方法: {{.FieldOrMethodName.New.Field1}}
 
- {{.Method1 "参数值1" "参数值2"}}: 调用方法“Method1”,将后面的参数值依次传递给此方法,并输出其返回值。
参数
模板参数可以是 Go 中的基本数据类型,亦可是数组切片或者一个结构体
在模板中定义变量: 变量名称由字母和数字组成,并附带 $ 前缀, 用 := 赋值
- 比如,{{$X := “ok”}} or {{$Y := “pipeline”}} 
- {{$FieldName}}: 用于输出在模板中定义的名称为 FieldName 的值,当 FieldName 本身是一个struct时,可访问其字段 
条件
Go的模板支持 bool 和 string 类型的条件判断, 语法格式如下:
|  |  | 
Note: 当.condition为bool类型时,值为true表示执行;当.condition为string类型时,值非空表示执行
内置的逻辑判断函数
- not 非- 1 2- {{if not .condition}} {{end}}- and 与
 - 1 2- {{if and .condition1 .condition2}} {{end}}
- or 或- 1 2- {{if or .condition1 .condition2}} {{end}}- eq 等于
 - 1 2- {{if eq .var1 .var2}} {{end}}
- ne 不等于- 1 2- {{if ne .var1 .var2}} {{end}}- lt 小于
 - 1 2- {{if lt .var1 .var2}} {{end}}
- le 小于等于- 1 2- {{if le .var1 .var2}} {{end}}- gt 大于
 - 1 2- {{if gt .var1 .var2}} {{end}}
- ge 大于等于- 1 2- {{if ge .var1 .var2}} {{end}}- 管道- Go模板的管道函数提供和Unix的pipe一样的功能,可用于过滤简化数据等 - 函数- Go的模板提供了自定义模板函数的功能:template包创建新模板的时候通过调用 - Funcs方法将自定义函数注册到该模板中,后续通过该模板渲染的文件均支持调用这些自定义函数- 函数集合定义- 自定义模板函数的集合定义: - 1- type FuncMap map[string]interface{}
Note:
- key: 方法名,用于模板字串或文件中调用
- value: 函数。该函数对其参数个数无限制,但对函数返回值有两种限制
- 只返回一个值
- 返回两个值,且第二个值必须为 error 类型
自定义和模板函数
- 创建一个 FuncMap类型的 map,key 为模板函数名称, value为函数定义 
- 将 FuncMap 注册到模板中 
Note:
- FuncMap注册必须在 Parse | ParseFiles之前
- 代码示例参考: 函数调用
函数调用
- {{FuncName}}- 调用 FuncName 模板函数(等同于执行 “FuncName()” 并输出其返回值)
 
- {{FuncName "Param1" "Param2"}}- 调用 FuncName(Param1, Param2), 并输出其返回值
- 例如: - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24- type Para struct { X int Y int } var tmpl2 = `Result is {{sum .X .Y}}` func TmplTest2() { funcMap := template.FuncMap{"sum": add} // 定义 FuncMap类型对象 t := template.New("Call func").Funcs(funcMap) // 注册 Funcmap到模板 t, _ = t.Parse(tmpl2) p := Para{ X: 1, Y: 2, } t.Execute(os.Stdout, p) } func add(x, y int) int { return x + y }
 
- {{.FieldName | FuncName}}- 将竖线 “|”左边的“.FieldName”变量值作为函数参数传送, 并输出其返回值。
 
- 将竖线 
遍历
对于数组,切片或map,可用迭代的action,与go的迭代类似,使用range:{{range ...}} ... {{end}}
遍历slice.1
遍历 slice,且获取其索引和值
| 1 2 3 | {{range $i, $v := .slice}}
    the value is {{$i}}, {{$v}}
{{end}} | 
Note:
- 在该循环中可通过
$i、$v访问遍历的值- range…end结构内部如要使用外部的变量,比如.Var2,需要这样写:$.Var2 ((即:在外部变量名称前加符号“$”即可,单独的“$”意义等同于global))
Code:
|  |  | 
遍历slice.2
| 1 2 3 | {{range .slice}}
    the value is {{.}}
{{end}} | 
Note: 该循环没有或取其index和value,需通过
.访问对应的值
Code:
|  |  | 
with·上下文
{{with ...}} ... {{end}}
with: 操作当前对象的值,类似上下文概念,其含义为创建一个封闭的作用域,在其范围内,可用 .action处理变量,而与外面的 . 无关,只与为with参数有关:
| 1 2 3 | {{with arg}}
    {{/* 此时的 . 就是arg */}}
{{end}} | 
Code:
|  |  | 
Note: with语句也可有 else,else中的点则和 with 外面的 . 作用一样
Must操作
模板包包含一个函数: Must,其作用为检测模板是否正确(例如:大括号是否匹配,注释是否正确关闭,变量是否是正确的书写)
|  |  | 
嵌套模板
子模板定义
| 1
 | {{define "子模板名称"}} 模板内容 {{end}} | 
子模板调用
| 1
 | {{template "子模板名称"}} | 
代码测试
Code: 定义三个模板文件,header.tmpl、content.tmpl、footer.tmpl测试嵌套模板
|  |  | 
|  |  | 
|  |  | 
|  |  | 
Output:
|  |  | 
Note:
- template.ParseFiles 可把所有嵌套模板解析到我们的模板对象
- 每一个 {{define “template_name”}} 定义的文件都是一个独立的模板文件,与其他模板文件并行存在; 解析后的模板文件在内部存储类似一种map结构,即key-表示模板名称,value-模板内容
- ExecuteTemplate()用来渲染定义好的子模板文件
子模板访问父模板变量
使用 {{template "content" .}} 可将当前变量传送给子模板
模板相关函数详解
Parse & ParseFiles & ParseBlob
函数定义:
|  |  | 
Note:
Parse用来解析一个字符串,字符串代表模版的内容,并且嵌套的模版也会和这个模版进行关联。
ParseFiles用来解析一组命名的文件模版,当模版定义在不同的文件中的时候,使用这个方法可以产生一个可执行的模版,模版执行的时候不会出错。
ParseGlob与ParseFiles类似,它使用filepath.Glob模式匹配的方式遍历文件,将这些文件生成模版- 两个函数还可以作为 *Template的方法使用。作为函数使用的时候,它返回模版的名字是第一个文件的名字,模版以第一个文件作为base模版。同时后面的文件也会生成模版作为这个模版的关联模板,你可以通过Lookup方法查找到这个模版,因为每个模版都保存着它的关联模版:
代码示例
Execute & ExecuteTemplate
函数定义
|  |  | 
Note:
Execute直接接收data的值渲染模板- 使用
ExecuteTemplate可以选择渲染 t 关联的模版作为渲染的主模版; name-指定主模版
See Also
Thanks to the authors 🙂