『Golang 内置模块库 template 』

时间:2022-05-31
本文章向大家介绍『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