• 服务端渲染

Golang为模板操作提供了丰富的支持,嵌套模板、导入函数、表示变量、迭代数据等都很简单。若需要比CSV数据格式更复杂的电脑关系,模板可能是一个不错的解决方案。模板的另一个 应用是网站的页面渲染。

Golang内置text/templatehtml/template两个模板库,html/template库为HTML提供了完整的支持,包括普通变量渲染、列表渲染、对象渲染等。

text/template是Golang标准库,实现数据驱动模板以生成文本输出,可理解为一组文本按照特定格式嵌套动态嵌入另一组文本中。可用来开发代码生成器。

text/template包是数据驱动的文本输出模板,即在编写好的模板中填充数据。一般而言,模板使用流程分为三个步骤:定义模板、解析模板、数据驱动模板。

$ vim main.go
package main

import (
    "os"
    "text/template"
)

func main() {
    //创建模板
    id := 100
    tmpl, err := template.New("tplname").Parse("id = {{.}}")
    if err != nil {
        panic(err)
    }
    //模板合并输出
    err = tmpl.Execute(os.Stdout, id)
    if err != nil {
        panic(err)
    }
}
$ go run main.go
id = 100

Action

  • {{.}}.点号表示传入模板的数据,数据不同渲染不同。
  • .点可代表Golang的任何类型,比如Struct、Map等。
  • {{}}包裹的内容统称为Actions

模板的输入文本是任何格式的UTF-8编码文本,,action可分为两种:

  • 数据求值(data evaluations)action数据求值的结果会直接复制到模板中
  • 控制结构(control structures)action控制结构和Golang程序类似,也是条件语句、循环语句、变量、函数调用等...

将模板成功解析后可安全地在并发环境中使用,若输出到同一个io.Writer数据可能会重叠,不能保证并发执行的先后顺序。

template.New

func New(name string) *Template

template.New()创建名为name的模板

package main

import (
    "os"
    "text/template"
)

func main() {
    //模板变量
    type User struct {
        Id   int
        Name string
    }
    user := User{100, "admin"}
    //创建模板
    tplname := "user"
    tmpl := template.New(tplname)
    //解析模板
    text := "id = {{.Id}} name = {{.Name}}"
    tpl, err := tmpl.Parse(text)
    if err != nil {
        panic(err)
    }
    //渲染输出
    err = tpl.Execute(os.Stdout, user)
    if err != nil {
        panic(err)
    }
}
$ go run main.go
id = 100 name = admin

template.Parse

func (t *Template) Parse(text string) (*Template, error)

template.Parse()方法将字符串text解析为模板,嵌套定义的模板会关联到最顶层t

template.Parse()可以多次调用,但只有第一次调用可以包含空格、注释、模板定义之外的文本。若后续调用解析后仍剩余文本会引发错误、返回nil、丢弃剩余文本。若解析得到的模板已有相关联的同名模板则会覆盖原模板。

template.ParseFiles

ParseFiles方法接收 一个字符串,字符串的内容是一个模板文件的路径,可为绝对路径或相对路径。

解析模板文件

$ vim view/default.html
id = {{.Id}} name = {{.Name}}

解析模板文件

$ vim main.go
package main

import (
    "os"
    "text/template"
)

func main() {
    //模板变量
    type User struct {
        Id   int
        Name string
    }
    user := User{100, "admin"}
    //创建模板
    tmpl, err := template.ParseFiles("./view/default.html")
    if err != nil {
        panic(err)
    }
    //模板合并输出
    err = tmpl.Execute(os.Stdout, user)
    if err != nil {
        panic(err)
    }
}
$ go run main.go
id = 100 name = admin

template.ExecuteTemplate

多模板时指定模板

package main

import (
    "os"
    "text/template"
)

func main() {
    //模板变量
    type User struct {
        Id   int
        Name string
    }
    user := User{100, "admin"}
    //创建模板
    tplname := "tplname"
    tmpl := template.New(tplname)
    //解析模板
    text := "id = {{.Id}} name = {{.Name}}"
    tpl, err := tmpl.Parse(text)
    if err != nil {
        panic(err)
    }
    //渲染输出
    err = tpl.ExecuteTemplate(os.Stdout, tplname, user)
    if err != nil {
        panic(err)
    }
}

template.Execute

template.Execute()方法将解析好的模板应用到data,并将输出写入wr。若执行时出现错误则会停止执行,但 有可能已经写入部分数据,模板可以安全的并发执行。

func (t *Template) Execute(wr io.Writer, data interface{}) (err error)

输出到指定文件

package main

import (
    "os"
    "text/template"
)

func main() {
    //模板变量
    type User struct {
        Id   int
        Name string
    }
    user := User{100, "admin"}
    //创建模板
    tplname := "tplname"
    tmpl := template.New(tplname)
    //解析模板
    text := "id = {{.Id}} name = {{.Name}}"
    tpl, err := tmpl.Parse(text)
    if err != nil {
        panic(err)
    }
    //输出文件
    file, err := os.OpenFile("./public/tpl.txt", os.O_CREATE|os.O_WRONLY, 0755)
    if err != nil {
        panic(err)
    }
    //渲染输出
    err = tpl.Execute(file, user)
    if err != nil {
        panic(err)
    }
}

读取模板文件解析后输出到指定位置

package main

import (
    "os"
    "text/template"
)

func main() {
    //模板变量
    type User struct {
        Id   int
        Name string
    }
    user := User{100, "admin"}
    //解析模板
    tplFile := "./view/default.html"
    tpl, err := template.ParseFiles(tplFile)
    if err != nil {
        panic(err)
    }
    //输出文件
    outFile := "./runtime/view/default.html"
    file, err := os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY, 0755)
    if err != nil {
        panic(err)
    }
    //渲染输出
    err = tpl.Execute(file, user)
    if err != nil {
        panic(err)
    }
}