Go语言 Web开发(9)模板处理

什么是模板?
在做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 编程

    原文作者:小杰的快乐时光
    原文地址: https://www.jianshu.com/p/4d798a02ff02
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞