1. Template 介绍
Go中提供了两种类型的template包:html/template 和 text/template 。前者用于前端项目,其中对一些特殊字符进行了安全转义操作,避免可能存在的安全问题。后者用于普通文件的渲染,比如 ansible 的清单文件或者k8s的yaml文件等。Template 模板使用语法如下:
- 模板文件后缀通常为 .tmpl 或者 .tpl,目的是方便区分。文件编码格式为 UTF-8
- 默认使用 {{ }} 标识变量或者关键字,可以人为修改
- 使用 . 标识传进来的数据,多个数据传递一般使用map方式,{{ .key }} 访问传递进来的数据中子字段
- 注释格式为
{{/* xxxx */}}注释不能嵌套,但是可以多行。
Template 一般使用步骤如下:
- 定义一个模板文件
- 解析模板文件
- 渲染模板文件
2. Template基本语法
2.1. 数据传递
2.1.1. 常见传递的数据类型
在模板语法中, {{ . }} 表示传递个模板的变量,仅支持一个变量。变量常用类型有:字符串,map,结构体和结构体指针,结构体指针在渲染后,也是结构体的值。如下案例,编译的时候需要注意可执行文件的路径,因为代码的模板文件为相对路径。
// templates/data.tmpldata: {{ . }}
import ("fmt""html/template""net/http")var tp *template.Templatefunc init() {var err errortp, err = template.ParseFiles("./templates/data.tmpl")if err != nil {fmt.Printf("template parse failed,err:%s\n", err.Error())return}}func f1(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, "Hello world!"); err != nil {_, _ = fmt.Fprint(w, "template operate failed!")return}}func f2(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, map[string]interface{}{"name": "ZhangSan","age": 18,}); err != nil {_, _ = fmt.Fprint(w, "template operate failed!")return}}func f3(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, struct {name stringage int}{name: "LiSi",age: 27,}); err != nil {_, _ = fmt.Fprint(w, "template operate failed!")return}}func f4(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, &struct {name stringage int}{name: "WanWu",age: 36,}); err != nil {_, _ = fmt.Fprint(w, "template operate failed!")return}}func main() {http.HandleFunc("/f1", f1) // 数据为 字符串http.HandleFunc("/f2", f2) // 数据为 maphttp.HandleFunc("/f3", f3) // 数据为结构体http.HandleFunc("/f4", f4) // 数据为结构体指针err := http.ListenAndServe("127.0.0.1:8080", nil)if err != nil {fmt.Printf("start http server failed, err:%s\n", err.Error())return}}
[root@duduniao go_learn]# curl 127.0.0.1:8080/f1data: Hello world![root@duduniao go_learn]# curl 127.0.0.1:8080/f2data: map[age:18 name:ZhangSan][root@duduniao go_learn]# curl 127.0.0.1:8080/f3data: {LiSi 27}[root@duduniao go_learn]# curl 127.0.0.1:8080/f4data: {WanWu 36}
2.1.2. 传递多个数据
在Go的模板中, {{ . }} 表示传递给模板的值,仅支持一个。但需要传递多个值的时候,有来两种方案:传递map或者结构体,采用 {{ .fieldName }} 方式获取字段的值。结构体想要对外可见,必须首字母大写,map根据Key取值时,如果取不到字段则为空,结构体取不到则报错。
// templates/data.tmplname: {{ .Name }}age: {{ .Age }}
import ("fmt""html/template""net/http")var tp *template.Templatefunc init() {var err errortp, err = template.ParseFiles("./templates/data.tmpl")if err != nil {fmt.Printf("template parse failed,err:%s\n", err.Error())return}}func f2(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, map[string]interface{}{"Name": "ZhangSan","Age": 18,}); err != nil {_, _ = fmt.Fprint(w, fmt.Sprintf("template operate failed, err:%s", err.Error()))return}}func f3(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, struct {Name stringAge int}{Name: "LiSi",Age: 27,}); err != nil {_, _ = fmt.Fprint(w, fmt.Sprintf("template operate failed, err:%s", err.Error()))return}}func f4(w http.ResponseWriter, r *http.Request) {if err := tp.Execute(w, &struct {Name stringAge int}{Name: "WanWu",Age: 36,}); err != nil {_, _ = fmt.Fprint(w, fmt.Sprintf("template operate failed, err:%s", err.Error()))return}}func main() {//http.HandleFunc("/f1", f1) // 数据为 字符串http.HandleFunc("/f2", f2) // 数据为 maphttp.HandleFunc("/f3", f3) // 数据为结构体http.HandleFunc("/f4", f4) // 数据为结构体指针err := http.ListenAndServe("127.0.0.1:8080", nil)if err != nil {fmt.Printf("start http server failed, err:%s\n", err.Error())return}}
[root@duduniao go_learn]# curl 127.0.0.1:8080/f2name: ZhangSanage: 18[root@duduniao go_learn]# curl 127.0.0.1:8080/f3name: LiSiage: 27[root@duduniao go_learn]# curl 127.0.0.1:8080/f4name: WanWuage: 36
2.2. 模板中自定义变量
使用 {{ $var := xxx }} 可以定义一个新的变量,引用的时候使用 {{ $var }} ,已经定义过的变量使用 {{ $var = xxx }} 。变量定义的所在行会产生空行,采用 {{- 或者 -}} 去除不必要的空行和空格。
{{- $var01 := . -}}Name: {{ $var01.Name }}Age: {{ $var01.Age }}{{ $var01 = "name: 张三" -}}{{ $var02 := "password: 123456" -}}info: {{ $var01}} - {{$var02}}
[root@duduniao go_learn]# curl 127.0.0.1:8080Name: 张三Age: 18info: name: 张三 - password: 123456
2.3. 条件判断
2.3.1. 条件判断常用函数
Golang 的Template将能输出数据的变量或者表达式称为 pipeline,if 条件判断有以下三种格式,和go语言基本一致,只需要注意格式。如果 pipeline 输出为该数据类型的零值则为 false。
{{if pipeline}} T1 {{end}}{{if pipeline}} T1 {{else}} T0 {{end}}{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
len 取pipeline的长度eq 如果arg1 == arg2则返回真ne 如果arg1 != arg2则返回真lt 如果arg1 < arg2则返回真le 如果arg1 <= arg2则返回真gt 如果arg1 > arg2则返回真ge 如果arg1 >= arg2则返回真
2.3.2. 条件判断案例
{{ if gt .Age 20 }}{{.Age }}gt than 20{{ else }}{{ .Aget }}le than 20{{ end }}{{ if .Addr }}Addr:{{.Addr}}{{end}}{{ if .Name }}Name:{{ .Name }}{{end}}
2.4. 遍历
使用 range 关键词可以实现对数组、切片、map和channel的遍历。遍历的过程中,如果需要取值则用 赋值的语句。
{{- range $k,$v := . -}}{{- if eq $k "hobby" -}}{{- range $i, $hobby := $v }}hobby: {{ $hobby }}{{ end }}{{ else }}{{ $k }} - {{ $v }}{{- end }}{{- end}}
