Go Templates
接下来使用Go的基础模板,使用html/template包开发成熟的web应用.
text/template包
使用模板创建动态内容是一个重要的方式,在运行时按照预定的格式生成动态的内容. 标准库html/template 包允许通过组合静态内容和动态内容创建动态的网页,动态内容会在运行时根据提供的数据结构进行解析转换.
html/template包提供了和text/template相同的接口,不同的是,html/template包通常是解析模板输出到HTML,text/template包则是文本的模板.以text/template开始,理解Go模板的语法,之后再使用html/template包. text/template 包可以创建数据驱动的模板得到输出的文本.
- 使用text/template
在运行的时候回根据给定的数据结构进行解析模板.模板的命令会反映到数据结构的元素.比如:结构体的字段可以映射到模板的命令,在模板中,这些命令会被双大括号包围 {{}}.
结构体字段应用到模板中的例子
// template
package main
import (
"log"
"os"
"text/template"
)
type Note struct {
Title string
Description string
}
const templ = `Note - Title:{{.Title}},Description:{{.Description}}`
func main() {
note := Note{"text/template", "Template generates textual ouput"}
//create a template with name
t := template.New("note")
//解析内容到模板
t, err := t.Parse(templ)
if err != nil {
log.Fatal("Parse:", err)
return
}
//将数据用到模板中
if err := t.Execute(os.Stdout, note); err != nil {
log.Fatal("Execute:", err)
return
}
}
//控制台输出
Note - Title:text/template,Description:Template generates textual ouput
在模板执行的时候,Note结构体的Title和Description字段会映射对象的值.模板快 {{.}}会在模板执行的时候进行上下文自动替换.此处的Note对象提供给了模板在模板执行的时候所以点(.)之后的字段会映射到Note对象对应的字段.
此处的模板是解析了一个字符串.如果是解析来自文件,使用 ParseFiles 方法
func (t *Template)ParseFiles(filenames ...string)(*Template ,error)
另外 ParseGlob方法会解析参数提供的表达式的对应模板.比如解析拓展名是 .tmpl的文件
t,err := template.ParseGlob("templates/*.tmpl")
Execute方法应用于一个解析过给定的数据对象的模板,同事写到一个输出设备.如果此时发生错误,执行会停止,但是可能有部分数据已经输出到设备.
总结起来解析一个文本模板的步骤如下:
1.定义一个映射到模板的数据对象
2.使用template.New方法创建一个*Template对象
3.调用Parse方法解析一个字符串到模板
4.执行模板的Execute方法,把给定的数据对象渲染到文本对象的字段.
下面的例子是把一个slice对象解析到模板中
// template
package main
import (
"log"
"os"
"text/template"
)
type Note struct {
Title string
Description string
}
const templ = `Notes are: {{range .}} Title:{{.Title}},Description:{{.Description}} {{end}}`
func main() {
notes := []Note{
{"text/template", "Template generates textual ouput"},
{"html/template", "Template generates HTML ouput"},
}
//create a template with name
t := template.New("note")
//解析内容到模板
t, err := t.Parse(templ)
if err != nil {
log.Fatal("Parse:", err)
return
}
//将数据用到模板中
if err := t.Execute(os.Stdout, notes); err != nil {
log.Fatal("Execute:", err)
return
}
}
//控制台输出
Notes are: Title:text/template,Description:Template generates textual ouput Title:html/template,Description:Template generates HTML ouput
- 定义明确命名的模板
模板定义可以使用 define和end来明确规定,define操作表示了模板的开始,end表示结束.
// define
package main
import (
"log"
"os"
"text/template"
)
func main() {
t, err := template.New("test").Parse(`{{define "T"}} Hello,{{.}}!{{end}}`)
err = t.ExecuteTemplate(os.Stdout, "T", "World")
if err != nil {
log.Fatal("Execute:", err)
}
}
//控制台输出
Hello World!
- 模板中声明变量
可以在模板中声明变量,在声明之后的内容可以直接使用.声明变量的方式:在{{}}内 $variable.
{{ $note := "Sample String"}} //声明
{{$note}} //调用变量
当使用range 函数获取到的变量,是每个枚举得出的元素.range得到key和value
{{range $key,$value := .}}
如果枚举的是字典,key就是字典的key值,value就是对应的value
使用html/template创建一个HTML页面
当我们创建web应用的时候,会用程序的数据去渲染UI界面.标准库的包html/template 可以很好的创建动态的web页面程序.我们创建web应用,会使用HTML,CSS和JavaScript创建好页面模板.
html/template 和text/template有相同的接口,但是输出到的是HTML页面.html/template不单单是生成HTML页面,还会防止代码的恶意注入.使用html/template包最多的优势在于安全的使用数据模型
这段代码展示了防止脚本注入:
// define
package main
import (
"html/template"
"log"
"os"
)
func main() {
t, err := template.New("test").Parse(`{{define "T"}} Hello,{{.}}!{{end}}`)
err = t.ExecuteTemplate(os.Stdout, "T", "<script>alert('haha')</script>")
if err != nil {
log.Fatal("Execute:", err)
}
}
//控制台输出
Hello,<script>alert('haha')</script>!