Go text/template

  • 服务端渲染

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)
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容