按照官方定义,template 包是数据驱动的文本输出模板,在预定义好的模板中填充好自己的数据。
text/template为go 内置包,无需下载可直接使用,使用需要包含template包
import “text/template”
一个简单的例子:
func example() {
str := "this is a simple example from {{.}}" //模板
tpl, err := template.New("test").Parse(str)
if err != nil {
fmt.Printf("failed %#v", err.Error())
return
}
data := "ctyun"
err = tpl.Execute(os.Stdout, data)
}
其输出:
this is a simple example from ctyun
要使用template ,完成以下步骤:
(1)首先要定义一个模板,模板为字符串类型,如上代码定义的str
(2)通过template.New函数新建一个模板,入参为模板的string类型的名称,然后调用新建模板的Parse方法,入参是自定义的模板,完成对模板的解析
(3)定义要输入模板的数据,上面的“ctyun”,调用模板的Execute方法,第一个参数是io.Writer类型,完成模板的渲染
模板:
`package {{.Name}}
import "fmt"
func main(){
fmt.Printf("%s","{{.Description}}")
}`
{{ 和 }} 中间的句号 .
代表传入模板的数据,根据传入的数据不同渲染不同的内容。.
可以代表 go 语言中的任何类型,如结构体、哈希等。
至于 {{ 和 }} 包裹的内容统称为 action,分为两种类型:
- 数据求值(data evaluations)
- 控制结构(control structures)
action 求值的结果会直接复制到模板中,控制结构和我们写 Go 程序差不多,也是条件语句、循环语句、变量、函数调用等
控制结构:
template支持控制结构,包括条件语句和循环语句,其格式如下
{{ if pipeline }} T1 {{ end }}
{{ if pipeline }} T1 {{ else }} T0 {{ end }}
{{ if pipeline }} T1 {{ else if pipeline }} T0 {{ end }}
循环语句:
{{ range pipeline }} T1 {{ end }}
{{ range $index, $value := pipeline }} T1 {{ end }}
如下例子:
type (
st1 struct {
Key uint32
Value uint32
Description string
}
st2 struct {
Name string
Member []st1
Description string
}}
func example1() {
data := st2{
Name: "layer2",
Member: []st1{
st1{
Key: 1,
Value: 100,
Description: "layer1 member1",
},
st1{
Key: 2,
Value: 200,
Description: "layer1 memeber2",
},
},
Description: "layer2",
}
str := `
exampl1:
layer1 info :
Name : {{.Name}}
Description: {{.Description}}
Member:
{{range $key,$data := .Member}}
{{if eq $key 1}}
mem{{$key}}
key:{{$data.Key}}
value:{{$data.Value}}
desc:{{$data.Description}}
{{else}}
mem{{$key}} stop printf
{{end}}
{{end}}
`
tpl, err := template.New("test").Parse(str)
if err != nil {
fmt.Printf("failed %#v", err.Error())
return
}
err = tpl.Execute(os.Stdout, data)
}
其输出:
exampl1:
layer1 info :
Name : layer2
Description: layer2
Member:
mem0 stop printf
mem1
key:2
value:200
desc:layer1 memeber2
变量:
action中可以使用变量,定义格式如下
{{ $exapmle := 0 }}
在控制结构中都可以定义变量,如上例子中
{{range $key,$data := .Member}}
定义了变量key 和data,循环获取输入数据.Member中的内容。在range,if 中使用变量,其作用域到{{end}}结尾。如果不是控制结构,声明的变量的作用域会扩展到整个模板
函数:
模板中可以定义函数,可使用的有两种
- 自定义的函数 map
- 全局函数 map,这些函数是模板内置的
自定义函数使用 func (t *Template) Funcs(funcMap FuncMap) *Template
注册,如下例子:
func example3() {
str := `
{{.A}} + {{.B}} = {{ add .A .B}}
`
data := struct {
A int
B int
}{
A: 1,
B: 2,
}
tpl, err := template.New("test").Funcs(template.FuncMap{
"add": func(a, b int) int { return a + b },
}).Parse(str)
if err != nil {
fmt.Printf("failed %#v", err.Error())
return
}
err = tpl.Execute(os.Stdout, data)
}
其中自定义了add 函数,并在模板中调用add函数,其输出如下:
1 + 2 = 3
内置的函数有:
- and:返回参数之间 and 布尔操作的结果
- or:逻辑操作符
||
,返回第一个能转换成 true 的值 - call:返回调用第一个函数参数的结果,函数必须有一个或两个回值(第二个返回值必须是 error,如果值不为 nil 会停止模板渲染)
- html:返回转义后的 HTML 字符串,这个函数不能在
html/template
中使用。 - js:返回转义后的 JavaScript 字符串。
- index:在第一个参数是 array、slice、map 时使用,返回对应下标的值。
- len:返回复合类型的长度。
- not:返回布尔类型参数的相反值。
- print:等于
fmt.Sprint
。 - printf:等于
fmt.Sprintf
。 - println:等于
fmt.Sprintln
。 - urlquery:对字符串进行 url Query 转义,不能在
html/template
包中使用。 - 比较函数:包括 eq: == ,ge: >=,gt: >,le: <=,lt: <,ne: !=