『Golang 内置模块库 template 』

封面.png

大家好,我叫谢伟,是一名程序员。

之前我推出了几个视频版的 golang 相关知识的讲解。看上去效果不好,毕竟简书作为写作平台,还是以阅读为主。

故以后的文章还是写出详细实例,最后再给出视频。各取所需吧。

本文的主题讲解:template 模板处理库

Package template implements data-driven templates for generating textual output.

即在MVC 设计模式的中View 层处理,html 文件中很多是静态数据,但也需要部分动态数据。template 库即是用来完成这个任务的, 即将动态数据填充入静态模板中。

机制如下:

My Name is {{ Name }}, you can call me {{ NickName }}

Name =  xieWei
NickName = xiexiaolu

结果:

My Name is xiewei, you can call me xiexiaolu

在Go 语言中如何使用 template ?

1. 官方实例

package main

import (
    "log"
    "os"
    "text/template"
)

func main() {
    // Define a template.
    const letter = `
Dear {{.Name}},
{{if .Attended}}
It was a pleasure to see you at the wedding.
{{- else}}
It is a shame you couldn't make it to the wedding.
{{- end}}
{{with .Gift -}}
Thank you for the lovely {{.}}.
{{end}}
Best wishes,
Josie
`

    // Prepare some data to insert into the template.
    type Recipient struct {
        Name, Gift string
        Attended   bool
    }
    var recipients = []Recipient{
        {"Aunt Mildred", "bone china tea set", true},
        {"Uncle John", "moleskin pants", false},
        {"Cousin Rodney", "", false},
    }

    // Create a new template and parse the letter into it.
    t := template.Must(template.New("letter").Parse(letter))

    // Execute the template for each recipient.
    for _, r := range recipients {
        err := t.Execute(os.Stdout, r)
        if err != nil {
            log.Println("executing template:", err)
        }
    }

}

结果:



Dear Aunt Mildred,

It was a pleasure to see you at the wedding.
Thank you for the lovely bone china tea set.

Best wishes,
Josie

Dear Uncle John,

It is a shame you couldn't make it to the wedding.
Thank you for the lovely moleskin pants.

Best wishes,
Josie

Dear Cousin Rodney,

It is a shame you couldn't make it to the wedding.

Best wishes,
Josie

Program exited.

2. 基本使用方法

1. 新建或者加载一个模板对象
type Template
    func New(name string) *Template
    func ParseFiles(filenames ...string) (*Template, error)
    func Must(t *Template, err error) *Template

即:比如: t := template.New("test template")

2. 加载模板, 定义动态数据占位符
func (t *Template) Parse(text string) (*Template, error)
func (t *Template) ParseFiles(filenames ...string) (*Template, error)

即:比如


var templateText = `This is a test for template:
Name: {{.Name}}
Age: {{.Age}}
School: {{.School}}
Married: {{.MarriedOK}}
`

t, err = t.Parse(templateText)



3. 定义动态数据,执行

var example = struct {
    Name    string
    Age     int
    School  string
    MarriedOK bool
}{
    Name:    "xiewei",
    Age:     18,
    School:  "shanghaiUniversity",
    MarriedOK: true,
}


t.Execute(os.Stdout, example)

结果:

This is a test for template
Name: xiewei
Age: 18
School: shanghaiUniversity
Married: true

3. 说明

1. 字段

  • {{.}} 表示当前字段
  • {{.Name}} 表示某个结构体的 Name 字段
  • 结构体字段需能被外部访问:即 字段首字母大写

2. 循环操作


{{range .Field}}
  {{.ChildFieldOne}}  -- {{.ChildFieldTwo }}
{{ end }}

3. 判断

{{if .Field}} if部分的输出 {{else}} else 部分的输出 {{end}}

4. pipelines

即:处理经由前面一个指令传出的正确输出信息,对错误信息信息没有直接处理能力

管道符: |

{{.Field | html }}

5. 模板函数

即:可以对某个字段使用函数操作。适用于稍微复杂的字段处理。

type FuncMap map[string]interface{}
t = t.Funcs(template.FuncMap{"handleFieldName": HandleFunc})


内置模板函数:

var builtins = FuncMap{
    "and":      and,
    "call":     call,
    "html":     HTMLEscaper,
    "index":    index,
    "js":       JSEscaper,
    "len":      length,
    "not":      not,
    "or":       or,
    "print":    fmt.Sprint,
    "printf":   fmt.Sprintf,
    "println":  fmt.Sprintln,
    "urlquery": URLQueryEscaper,
}

4. 示例

package main

import (
    "fmt"
    "html/template"
    "os"
)

var Text = `
This is a test Template:
Name: {{.Name}}
Age:{{.Age}}
Married: {{.Married}}
School: {{.School}}
`

var TextTwo = `
This is a test Template:
Name: {{.Name |handleString | printf }}
Age: {{.Age | handleInt}}
Married: {{.Married }}
School: {{.School | handleString}}
`

var TextThree = `
{{if .Fields }}{{range .Fields }}
   Name: {{.Name}} - Age:{{.Age}} - School:{{.School}} - Married:{{.Married}}
{{ end }}{{end}}
{{if .Names}}{{ range .Names }}   {{.}} {{ end }}{{end}}
`

type Information struct {
    Name    string
    Age     int
    Married bool
    School  string
}

func (this Information) String() string {
    return fmt.Sprintf(`
This is a test String interface.
Name: %s
Age: %d
Married: %t
School: %s
`, this.Name, this.Age, this.Married, this.School)

}

func (this Information) Template(text string) {
    var (
        t *template.Template
    )
    t = template.New("New template for information")
    var (
        err error
    )

    if t, err = t.Parse(text); err != nil {
        fmt.Println("Template parse err" + err.Error())
        return
    }
    t.Execute(os.Stdout, this)
}

func (this Information) TemplateWithFuncMap(text string) {
    var (
        t   *template.Template
        err error
    )
    t = template.New("123").Funcs(InfoFuncMap())
    //t = template.New("template with funcmap")
    //t = t.Funcs(template.FuncMap{"handleString": handleString,
    //  "handleInt": handleInt})
    if t, err = t.Parse(text); err != nil {
        fmt.Println("err" + err.Error())
        return
    }
    t.Execute(os.Stdout, this)

}
func InfoFuncMap() template.FuncMap {
    return template.FuncMap{
        "handleString": handleString,
        "handleInt":    handleInt,
    }
}
func handleString(field string) string {
    if field == "" {
        return "None"
    } else {
        return " xiewei-test-for: " + field
    }
}

func handleInt(number int) int {
    return number + 20
}

type NewInformation struct {
    Fields []Information
    Names  []string
}

func RangeTemplate(args NewInformation, text string) {
    var (
        t   *template.Template
        err error
    )
    t = template.New("new template")
    if t, err = t.Parse(text); err != nil {
        fmt.Println("err" + err.Error())
        return
    }
    t.Execute(os.Stdout, args)

}

func main() {
    var (
        newInfor Information
    )
    newInfor = Information{
        Name:    "xiewei",
        Age:     18,
        School:  "shanghaiUniversity",
        Married: true,
    }
    fmt.Println("1")
    fmt.Println(newInfor)
    fmt.Println("2")
    newInfor.Template(Text)
    fmt.Println("3")
    newInfor.TemplateWithFuncMap(TextTwo)
    fmt.Println("4")
    var (
        newInformations NewInformation
    )
    newInformations = NewInformation{
        Fields: []Information{
            Information{Name: "xiexiaolu", Age: 19, Married: false, School: "pekingUniversity"},
            Information{Name: "xiexie", Age: 20, Married: true, School: "XXXXX"},
        },
        Names: []string{
            "jiewu", "baidu", "google", "aiqiyi", "wangyi",
        },
    }
    RangeTemplate(newInformations, TextThree)
}


结果:


1

This is a test String interface.
Name: xiewei
Age: 18
Married: true
School: shanghaiUniversity

2

This is a test Template:
Name: xiewei
Age:18
Married: true
School: shanghaiUniversity
3

This is a test Template:
Name:  xiewei-test-for: xiewei
Age: 38
Married: true
School:  xiewei-test-for: shanghaiUniversity
4


   Name: xiexiaolu - Age:19 - School:pekingUniversity - Married:false

   Name: xiexie - Age:20 - School:XXXXX - Married:true

   jiewu    baidu    google    aiqiyi    wangyi 


5. 视频

唉 , 我好像英文发音不准叻。我会注意的。

Golang template 讲解视频

6. 开源库处理方式

func Tmpl(text string, data interface{}) {
    output := colors.NewColorWriter(os.Stderr)

    t := template.New("Usage").Funcs(BeeFuncMap())
    template.Must(t.Parse(text))

    err := t.Execute(output, data)
    if err != nil {
        beeLogger.Log.Error(err.Error())
    }
}
func BeeFuncMap() template.FuncMap {
    return template.FuncMap{
        "trim":       strings.TrimSpace,
        "bold":       colors.Bold,
        "headline":   colors.MagentaBold,
        "foldername": colors.RedBold,
        "endline":    EndLine,
        "tmpltostr":  TmplToString,
    }
}

var usageTemplate = `Bee is a Fast and Flexible tool for managing your Beego Web Application.

{{"USAGE" | headline}}
    {{"bee command [arguments]" | bold}}

{{"AVAILABLE COMMANDS" | headline}}
{{range .}}{{if .Runnable}}
    {{.Name | printf "%-11s" | bold}} {{.Short}}{{end}}{{end}}

Use {{"bee help [command]" | bold}} for more information about a command.

{{"ADDITIONAL HELP TOPICS" | headline}}
{{range .}}{{if not .Runnable}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use {{"bee help [topic]" | bold}} for more information about that topic.
`

var AppHelpTemplate = `NAME:
   {{.Name}}{{if .Usage}} - {{.Usage}}{{end}}

USAGE:
   {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}

VERSION:
   {{.Version}}{{end}}{{end}}{{if .Description}}

DESCRIPTION:
   {{.Description}}{{end}}{{if len .Authors}}

AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
   {{range $index, $author := .Authors}}{{if $index}}
   {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}

COMMANDS:{{range .VisibleCategories}}{{if .Name}}

   {{.Name}}:{{end}}{{range .VisibleCommands}}
     {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}

GLOBAL OPTIONS:
   {{range $index, $option := .VisibleFlags}}{{if $index}}
   {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}

COPYRIGHT:
   {{.Copyright}}{{end}}
`

网盘:链接 密码:475u

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

推荐阅读更多精彩内容