什么是模板?
在做JavaWeb开发时,经常会在JSP页面中通过插入 <%=….=%>来实现插入动态语言生成数据,而在Go语言中也有类似的功能处理。
Go模板的使用
在Go语言中,我们使用 template 包来进行模板处理,使用类似 Parse 、 ParseFile 、 Execute 等方法从文件或者字符串加载模板,然后执行类似上面图片展示的模板的merge操作。
模板规则
模板是一个包含了一个或多个双花括号标记({{…}})的字符串,这种双花括标记号叫做Action。模板中所有的除Action的字符串都按照原样打印。通过Action可以打印变量的值、字段的值、调用函数或方法、表达控制流程等。 {{.}} 表示当前的对象,这和Java或者C++中的this类似,如果要访问当前对象的字段通过 {{.FieldName}} ,但是需要注意一点:这个字段必须是导出的(字段首字母必须是大写的),否则在渲染的时候就会报错。
相关函数:
text/template与html/template提供了相同的API来创建、解析和执行模板,区别是html/template提供了HTML转义。
// 创建一个名字为name的模板
func New(name string) *Template
// 解析模板字符串
func (t *Template) Parse(text string) (*Template, error)
// 解析文件
func ParseFiles(filenames ...string) (*Template, error)
// 执行模板,将结果写入wr
func (t *Template) Execute(wr io.Writer, data interface{}) error
使用Must()来处理Parse()的结果,作用是检测模板是否正确,例如大括号是否匹配,注释是否正确的关闭,变量是否正确的书写
如果Parse()失败,则调用panic(),如果成功,返回Template对象。
func Must(t *Template, err error) *Template
Funcs()用来给函数注册模板,注册之后模板就可以通过名字调用外部函数了
func (t *Template) Funcs(funcMap FuncMap) *Template
示例一:普通创建模板
import (
"html/template"
"log"
"os"
)
func main() {
//创建一个 Welcome 模板,并解析指定字符串
tem,err := template.New("Welcome").Parse("Hello {{.}},Welcome come to Go")
if err != nil {
log.Fatal(err)
}
//执行模板,传入对应的参数
tem.Execute(os.Stdout,"zengjie")
}
----output----
Hello zengjie,Welcome come to Go
示例二:访问结构体字段
func main() {
//emplate访问结构体字段时利用了反射机制,因此必须导出字段才能在模板里访问
tem:= template.Must(template.New("Welcome").Parse("Hello {{.Name}} {{.Age}},Welcome come to Go"))
//执行模板,传入对应的参数
//tem.Execute(os.Stdout,"zengjie")
tem.Execute(os.Stdout, struct {
Name string
age int
}{"zengjie",12})
}
----output----
Hello zengjie 12,Welcome come to Go
注意:{{.Age}}中的Age与struct { Age int } 必须都是大写才能正确被输出
示例三:循环输出
可以使用 {{with …}}…{{end}} 和 {{range …}}{{end}} 来表示循环数据输出,每次迭代中点(.)代表当前迭代的值。
{{range}}:这个和Go语法里面的range类似,循环操作数据
{{with}}:操作是指当前对象的值,类似上下文的概念
type Car struct {
CarName string
CarType string
Wheels []*Wheel
}
type Wheel struct {
WheelName string
}
func main() {
//创建车的四个轮子
wheel1 := Wheel{WheelName:"前轮"}
wheel2 := Wheel{WheelName:"后轮"}
wheel3 := Wheel{WheelName:"左轮"}
wheel4 := Wheel{WheelName:"右轮"}
//创建一辆车
car := Car{CarName:"红旗",CarType:"国产",Wheels:[]*Wheel{&wheel1,&wheel2,&wheel3,&wheel4}}
//创建新模板
tem := template.New("Car Tempplate")
tem,err := tem.Parse("This is {{.CarName}}! it is {{.CarType}},have {{range .Wheels}} {{.}} {{end}} ")
if err == nil {
tem.Execute(os.Stdout,car)
}
}
----output----
This is 红旗! it is 国产,have {前轮} {后轮} {左轮} {右轮}
将上面的 {{range …}}{{end}} 改为 {{with …}}…{{end}},结果不变。
tem,err := tem.Parse("This is {{.CarName}}! it is {{.CarType}},have {{with.Wheels}} {{range.}} {{.WheelName}} {{end}}{{end}} ")
示例四:条件处理 if else
模板中使用if else判断,格式为:if bool + 输出内容+ else +输出内容,if后面只能跟bool类型的值,无法使用条件判断,如1==1等
Execute(os.Stdout, value)的value值如果为空,则if会认为是false,反之认为是true
tEmpty := template.New("template test")
tEmpty = template.Must(tEmpty.Parse(" {{if true}}内容输出111{{end}}\n"))
tEmpty.Execute(os.Stdout, nil)
-----output-----
内容输出111
tWithValue := template.New("template test")
tWithValue = template.Must(tWithValue.Parse("{{if false}}内容输出111 {{end}}\n"))
tWithValue.Execute(os.Stdout, "abc")
----output----
无输出内容
tIfElse := template.New("template test")
tIfElse = template.Must(tIfElse.Parse("{{if false}}if部分{{else}}else部分{{end}}\n"))
tIfElse.Execute(os.Stdout, nil)
----output----
else部分
示例五:用 | 将其左边的输出作为其右边的输入
func main() {
const temStr = `{{. | printf "%v"}}`
t := template.Must(template.New("Welcome").Parse(temStr))
t.Execute(os.Stdout, "zengjie")
}
示例七:模板调用函数
//外部函数
func Welcome(name string) string {
return "Welcome, " + name + "!"
}
func main() {
const temStr = `{{. |Welco}}`
//通过Funcs()来将函数注册为模板,FuncMap(K:函数别名,v:对应的函数)
t := template.Must(template.New("report").Funcs(template.FuncMap{"Welco": Welcome}).Parse(temStr))
t.Execute(os.Stdout, "zengjie")
}
----output----
Welcome, zengjie!
示例八:模板嵌套
一个网页可以分为上,中,下三部分,那么在嵌套时也可以划分为三个模块的组合,分为以下几个步骤:
①定义三个文件, header.tmpl 、 content.tmpl 、 footer.tmpl 文件
//header.tmpl
{{define "header"}}
<html>
<head>
<meta charset="UTF-8">
<title> 演示信息 </title>
</head>
<body>
{{end}}
//content.tmpl
{{define "content"}}
{{template "header"}}
<h1> 演示嵌套 </h1>
<ul>
<li> 嵌套使用 define 定义子模板 </li>
<li> 调用使用 template</li>
</ul>
{{template "footer"}}
{{end}}
//footer.tmpl
{{define "footer"}}
</body>
</html>
{{end}}
②后台代码如下:
import (
"fmt"
"os"
"text/template"
)
func main() {
// 通过 template.ParseFiles 把所有的嵌套模板全部解析到模板
s1, _ := template.ParseFiles("header.tmpl", "content.tmpl", "footer.tmpl")
s1.ExecuteTemplate(os.Stdout, "header", nil)
fmt.Println()
s1.ExecuteTemplate(os.Stdout, "content", nil)
fmt.Println()
s1.ExecuteTemplate(os.Stdout, "footer", nil)
fmt.Println()
s1.Execute(os.Stdout, nil)
}
参考文章:https://blog.csdn.net/u011304970/article/details/71195675
参考书籍:Go Web 编程