Go 语言

Go 语言教程 Go 语言环境安装 Go 语言结构 Go 语言基础语法 Go 语言数据类型 Go 语言变量 Go 语言常量 Go 语言运算符 Go 语言条件语句 Go 语言 if 语句 Go 语言 if...else 语句 Go 语言 if 语句嵌套 Go 语言 switch 语句 Go 语言 select 语句 Go 语言循环语句 Go 语言 for 循环 Go 语言循环嵌套 Go 语言 break 语句 Go 语言 continue 语句 Go 语言 goto 语句 Go 语言函数 Go 语言函数值传递值 Go 语言函数引用传递值 Go 语言函数作为值 Go 语言函数闭包 Go 语言函数方法 Go 语言变量作用域 Go 语言数组 Go 语言多维数组 Go 语言向函数传递数组 Go 语言指针 Go 语言指针数组 Go 语言指向指针的指针 Go 语言指针作为函数参数 Go 语言结构体 Go 语言切片(Slice) Go 语言范围(Range) Go 语言Map(集合) Go 语言递归函数 Go 语言类型转换 Go 语言接口 Go 错误处理 Go 语言开发工具Go 语言标准库

Go 语言标准库


package template

import "text/template"

template包实现了数据驱动的用于生成文本输出的模板。

如果要生成HTML格式的输出,参见html/template包,该包提供了和本包相同的接口,但会自动将输出转化为安全的HTML格式输出,可以抵抗一些网络攻击。

通过将模板应用于一个数据结构(即该数据结构作为模板的参数)来执行,来获得输出。模板中的注释引用数据接口的元素(一般如结构体的字段或者字典的键)来控制执行过程和获取需要呈现的值。模板执行时会遍历结构并将指针表示为'.'(称之为"dot")指向运行过程中数据结构的当前位置的值。

用作模板的输入文本必须是utf-8编码的文本。"Action"—数据运算和控制单位—由"{{"和"}}"界定;在Action之外的所有文本都不做修改的拷贝到输出中。Action内部不能有换行,但注释可以有换行。

经解析生成模板后,一个模板可以安全的并发执行。

下面是一个简单的例子,可以打印"17 of wool"。

type Inventory struct {
	Material string
	Count    uint
}
sweaters := Inventory{"wool", 17}
tmpl, err := template.New("test").Parse("{{.Count}} of {{.Material}}")
if err != nil { panic(err) }
err = tmpl.Execute(os.Stdout, sweaters)
if err != nil { panic(err) }

更复杂的例子在下面。

Actions

下面是一个action(动作)的列表。"Arguments"和"pipelines"代表数据的执行结果,细节定义在后面。

{{/* a comment */}}
    注释,执行时会忽略。可以多行。注释不能嵌套,并且必须紧贴分界符始止,就像这里表示的一样。
{{pipeline}}
    pipeline的值的默认文本表示会被拷贝到输出里。
{{if pipeline}} T1 {{end}}
    如果pipeline的值为empty,不产生输出,否则输出T1执行结果。不改变dot的值。
    Empty值包括false、0、任意nil指针或者nil接口,任意长度为0的数组、切片、字典。
{{if pipeline}} T1 {{else}} T0 {{end}}
    如果pipeline的值为empty,输出T0执行结果,否则输出T1执行结果。不改变dot的值。
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
    用于简化if-else链条,else action可以直接包含另一个if;等价于:
        {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
{{range pipeline}} T1 {{end}}
    pipeline的值必须是数组、切片、字典或者通道。
    如果pipeline的值其长度为0,不会有任何输出;
    否则dot依次设为数组、切片、字典或者通道的每一个成员元素并执行T1;
    如果pipeline的值为字典,且键可排序的基本类型,元素也会按键的顺序排序。
{{range pipeline}} T1 {{else}} T0 {{end}}
    pipeline的值必须是数组、切片、字典或者通道。
    如果pipeline的值其长度为0,不改变dot的值并执行T0;否则会修改dot并执行T1。
{{template "name"}}
    执行名为name的模板,提供给模板的参数为nil,如模板不存在输出为""
{{template "name" pipeline}}
    执行名为name的模板,提供给模板的参数为pipeline的值。
{{with pipeline}} T1 {{end}}
    如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot。
{{with pipeline}} T1 {{else}} T0 {{end}}
    如果pipeline为empty,不改变dot并执行T0,否则dot设为pipeline的值并执行T1。

Arguments

参数代表一个简单的,由下面的某一条表示的值:

- go语法的布尔值、字符串、字符、整数、浮点数、虚数、复数,视为无类型字面常数,字符串不能跨行
- 关键字nil,代表一个go的无类型的nil值
- 字符'.'(句点,用时不加单引号),代表dot的值
- 变量名,以美元符号起始加上(可为空的)字母和数字构成的字符串,如:$piOver2和$;
  执行结果为变量的值,变量参见下面的介绍
- 结构体数据的字段名,以句点起始,如:.Field;
  执行结果为字段的值,支持链式调用:.Field1.Field2;
  字段也可以在变量上使用(包括链式调用):$x.Field1.Field2;
- 字典类型数据的键名;以句点起始,如:.Key;
  执行结果是该键在字典中对应的成员元素的值;
  键也可以和字段配合做链式调用,深度不限:.Field1.Key1.Field2.Key2;
  虽然键也必须是字母和数字构成的标识字符串,但不需要以大写字母起始;
  键也可以用于变量(包括链式调用):$x.key1.key2;
- 数据的无参数方法名,以句点为起始,如:.Method;
  执行结果为dot调用该方法的返回值,dot.Method();
  该方法必须有1到2个返回值,如果有2个则后一个必须是error接口类型;
  如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用模板执行者该错误;
  方法可和字段、键配合做链式调用,深度不限:.Field1.Key1.Method1.Field2.Key2.Method2;
  方法也可以在变量上使用(包括链式调用):$x.Method1.Field;
- 无参数的函数名,如:fun;
  执行结果是调用该函数的返回值fun();对返回值的要求和方法一样;函数和函数名细节参见后面。
- 上面某一条的实例加上括弧(用于分组)
  执行结果可以访问其字段或者键对应的值:
      print (.F1 arg1) (.F2 arg2)
      (.StructValuedMethod "arg").Field

Arguments可以是任何类型:如果是指针,在必要时会自动表示为指针指向的值;如果执行结果生成了一个函数类型的值,如结构体的函数类型字段,该函数不会自动调用,但可以在if等action里视为真。如果要调用它,使用call函数,参见下面。

Pipeline是一个(可能是链状的)command序列。Command可以是一个简单值(argument)或者对函数或者方法的(可以有多个参数的)调用:

Argument
    执行结果是argument的执行结果
.Method [Argument...]
    方法可以独立调用或者位于链式调用的末端,不同于链式调用中间的方法,可以使用参数;
    执行结果是使用给出的参数调用该方法的返回值:dot.Method(Argument1, etc.);
functionName [Argument...]
    执行结果是使用给定的参数调用函数名指定的函数的返回值:function(Argument1, etc.);

Pipelines

pipeline通常是将一个command序列分割开,再使用管道符'|'连接起来(但不使用管道符的command序列也可以视为一个管道)。在一个链式的pipeline里,每个command的结果都作为下一个command的最后一个参数。pipeline最后一个command的输出作为整个管道执行的结果。

command的输出可以是1到2个值,如果是2个后一个必须是error接口类型。如果error类型返回值非nil,模板执行会中止并将该错误返回给执行模板的调用者。

Variables

Action里可以初始化一个变量来捕获管道的执行结果。初始化语法如下:

$variable := pipeline

其中$variable是变量的名字。声明变量的action不会产生任何输出。

如果"range" action初始化了1个变量,该变量设置为迭代器的每一个成员元素,如果初始化了逗号分隔的2个变量:

range $index, $element := pipeline

这时,$index和$element分别设置为数组/切片的索引或者字典的键,以及对应的成员元素。注意这和go range从句只有一个参数时设置为索引/键不同!

一个变量的作用域只到声明它的控制结构("if"、"with"、"range")的"end"为止,如果不是在控制结构里声明会直到模板结束为止。子模板的调用不会从调用它的位置(作用域)继承变量。

模板开始执行时,$会设置为传递给Execute方法的参数,就是说,dot的初始值。

Examples

下面是一些单行模板,展示了pipeline和变量。所有都生成加引号的单词"output":

{{"\"output\""}}
	字符串常量
{{`"output"`}}
	原始字符串常量
{{printf "%q" "output"}}
	函数调用
{{"output" | printf "%q"}}
	函数调用,最后一个参数来自前一个command的返回值
{{printf "%q" (print "out" "put")}}
	加括号的参数
{{"put" | printf "%s%s" "out" | printf "%q"}}
	玩出花的管道的链式调用
{{"output" | printf "%s" | printf "%q"}}
	管道的链式调用
{{with "output"}}{{printf "%q" .}}{{end}}
	使用dot的with action
{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
	创建并使用变量的with action
{{with $x := "output"}}{{printf "%q" $x}}{{end}}
	将变量使用在另一个action的with action
{{with $x := "output"}}{{$x | printf "%q"}}{{end}}
	以管道形式将变量使用在另一个action的with action  

Functions

执行模板时,函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一般不在模板内定义函数,而是使用Funcs方法添加函数到模板里。

预定义的全局函数如下:

and
    函数返回它的第一个empty参数或者最后一个参数;
    就是说"and x y"等价于"if x then y else x";所有参数都会执行;
or
    返回第一个非empty参数或者最后一个参数;
    亦即"or x y"等价于"if x then x else y";所有参数都会执行;
not
    返回它的单个参数的布尔值的否定
len
    返回它的参数的整数类型长度
index
    执行结果为第一个参数以剩下的参数为索引/键指向的值;
    如"index x 1 2 3"返回x[1][2][3]的值;每个被索引的主体必须是数组、切片或者字典。
print
    即fmt.Sprint
printf
    即fmt.Sprintf
println
    即fmt.Sprintln
html
    返回其参数文本表示的HTML逸码等价表示。
urlquery
    返回其参数文本表示的可嵌入URL查询的逸码等价表示。
js
    返回其参数文本表示的JavaScript逸码等价表示。
call
    执行结果是调用第一个参数的返回值,该参数必须是函数类型,其余参数作为调用该函数的参数;
    如"call .X.Y 1 2"等价于go语言里的dot.X.Y(1, 2);
    其中Y是函数类型的字段或者字典的值,或者其他类似情况;
    call的第一个参数的执行结果必须是函数类型的值(和预定义函数如print明显不同);
    该函数类型值必须有1到2个返回值,如果有2个则后一个必须是error接口类型;
    如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用模板执行者该错误;

布尔函数会将任何类型的零值视为假,其余视为真。

下面是定义为函数的二元比较运算的集合:

eq      如果arg1 == arg2则返回真
ne      如果arg1 != arg2则返回真
lt      如果arg1 < arg2则返回真
le      如果arg1 <= arg2则返回真
gt      如果arg1 > arg2则返回真
ge      如果arg1 >= arg2则返回真

为了简化多参数相等检测,eq(只有eq)可以接受2个或更多个参数,它会将第一个参数和其余参数依次比较,返回下式的结果:

arg1==arg2 || arg1==arg3 || arg1==arg4 ...

(和go的||不一样,不做惰性运算,所有参数都会执行)

比较函数只适用于基本类型(或重定义的基本类型,如"type Celsius float32")。它们实现了go语言规则的值的比较,但具体的类型和大小会忽略掉,因此任意类型有符号整数值都可以互相比较;任意类型无符号整数值都可以互相比较;等等。但是,整数和浮点数不能互相比较。

Associated templates

每一个模板在创建时都要用一个字符串命名。同时,每一个模板都会和0或多个模板关联,并可以使用它们的名字调用这些模板;这种关联可以传递,并形成一个模板的名字空间。

一个模板可以通过模板调用实例化另一个模板;参见上面的"template" action。name必须是包含模板调用的模板相关联的模板的名字。

Nested template definitions

当解析模板时,可以定义另一个模板,该模板会和当前解析的模板相关联。模板必须定义在当前模板的最顶层,就像go程序里的全局变量一样。

这种定义模板的语法是将每一个子模板的声明放在"define"和"end" action内部。

define action使用给出的字符串常数给模板命名,举例如下:

`{{define "T1"}}ONE{{end}}
{{define "T2"}}TWO{{end}}
{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
{{template "T3"}}`

它定义了两个模板T1和T2,第三个模板T3在执行时调用这两个模板;最后该模板调用了T3。输出结果是:

ONE TWO

采用这种方法,一个模板只能从属于一个关联。如果需要让一个模板可以被多个关联查找到;模板定义必须多次解析以创建不同的*Template 值,或者必须使用Clone或AddParseTree方法进行拷贝。

可能需要多次调用Parse函数以集合多个相关的模板;参见ParseFiles和ParseGlob函数和方法,它们提供了简便的途径去解析保存在文件中的存在关联的模板。

一个模板可以直接调用或者通过ExecuteTemplate方法调用指定名字的相关联的模板;我们可以这样调用模板:

err := tmpl.Execute(os.Stdout, "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

或显式的指定模板的名字来调用:

err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
if err != nil {
	log.Fatalf("execution failed: %s", err)
}

Go语言标准库 >>


  • func HTMLEscape(w io.Writer, b []byte)
  • func HTMLEscapeString(s string) string
  • func HTMLEscaper(args ...interface{}) string
  • func JSEscape(w io.Writer, b []byte)
  • func JSEscapeString(s string) string
  • func JSEscaper(args ...interface{}) string
  • func URLQueryEscaper(args ...interface{}) string
  • type FuncMap
  • type Template
  • Examples

    Go语言标准库 >>


  • Template
  • Template (Func)
  • Template (Glob)
  • Template (Helpers)
  • Template (Share)
  • func HTMLEscape

    func HTMLEscape(w io.Writer, b []byte)

    函数向w中写入b的HTML转义等价表示。

    func HTMLEscapeString

    func HTMLEscapeString(s string) string

    返回s的HTML转义等价表示字符串。

    func HTMLEscaper

    func HTMLEscaper(args ...interface{}) string

    函数返回其所有参数文本表示的HTML转义等价表示字符串。

    func JSEscape

    func JSEscape(w io.Writer, b []byte)

    函数向w中写入b的JavaScript转义等价表示。

    func JSEscapeString

    func JSEscapeString(s string) string

    返回s的JavaScript转义等价表示字符串。

    func JSEscaper

    func JSEscaper(args ...interface{}) string

    函数返回其所有参数文本表示的JavaScript转义等价表示字符串。

    func URLQueryEscaper

    func URLQueryEscaper(args ...interface{}) string

    函数返回其所有参数文本表示的可以嵌入URL查询的转义等价表示字符串。

    type FuncMap

    type FuncMap map[string]interface{}

    FuncMap类型定义了函数名字符串到函数的映射,每个函数都必须有1到2个返回值,如果有2个则后一个必须是error接口类型;如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用者该错误。

    type Template

    type Template struct {
        *parse.Tree
        // 内含隐藏或非导出字段
    }

    代表一个解析好的模板,*parse.Tree字段仅仅是暴露给html/template包使用的,因此其他人应该视字段未导出。

    Example
    // 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)
        }
    }

    Output:

    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
    
    Example (Func)
    // First we create a FuncMap with which to register the function.
    funcMap := template.FuncMap{
        // The name "title" is what the function will be called in the template text.
        "title": strings.Title,
    }
    // A simple template definition to test our function.
    // We print the input text several ways:
    // - the original
    // - title-cased
    // - title-cased and then printed with %q
    // - printed with %q and then title-cased.
    const templateText = `
    Input: {{printf "%q" .}}
    Output 0: {{title .}}
    Output 1: {{title . | printf "%q"}}
    Output 2: {{printf "%q" . | title}}
    `
    // Create a template, add the function map, and parse the text.
    tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText)
    if err != nil {
        log.Fatalf("parsing: %s", err)
    }
    // Run the template to verify the output.
    err = tmpl.Execute(os.Stdout, "the go programming language")
    if err != nil {
        log.Fatalf("execution: %s", err)
    }

    Output:

    Input: "the go programming language"
    Output 0: The Go Programming Language
    Output 1: "The Go Programming Language"
    Output 2: "The Go Programming Language"
    
    Example (Glob)
    // Here we create a temporary directory and populate it with our sample
    // template definition files; usually the template files would already
    // exist in some location known to the program.
    dir := createTestDir([]templateFile{
        // T0.tmpl is a plain template file that just invokes T1.
        {"T0.tmpl", `T0 invokes T1: ({{template "T1"}})`},
        // T1.tmpl defines a template, T1 that invokes T2.
        {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
        // T2.tmpl defines a template T2.
        {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
    })
    // Clean up after the test; another quirk of running as an example.
    defer os.RemoveAll(dir)
    // pattern is the glob pattern used to find all the template files.
    pattern := filepath.Join(dir, "*.tmpl")
    // Here starts the example proper.
    // T0.tmpl is the first name matched, so it becomes the starting template,
    // the value returned by ParseGlob.
    tmpl := template.Must(template.ParseGlob(pattern))
    err := tmpl.Execute(os.Stdout, nil)
    if err != nil {
        log.Fatalf("template execution: %s", err)
    }

    Output:

    T0 invokes T1: (T1 invokes T2: (This is T2))
    
    Example (Helpers)
    // Here we create a temporary directory and populate it with our sample
    // template definition files; usually the template files would already
    // exist in some location known to the program.
    dir := createTestDir([]templateFile{
        // T1.tmpl defines a template, T1 that invokes T2.
        {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
        // T2.tmpl defines a template T2.
        {"T2.tmpl", `{{define "T2"}}This is T2{{end}}`},
    })
    // Clean up after the test; another quirk of running as an example.
    defer os.RemoveAll(dir)
    // pattern is the glob pattern used to find all the template files.
    pattern := filepath.Join(dir, "*.tmpl")
    // Here starts the example proper.
    // Load the helpers.
    templates := template.Must(template.ParseGlob(pattern))
    // Add one driver template to the bunch; we do this with an explicit template definition.
    _, err := templates.Parse("{{define `driver1`}}Driver 1 calls T1: ({{template `T1`}})\n{{end}}")
    if err != nil {
        log.Fatal("parsing driver1: ", err)
    }
    // Add another driver template.
    _, err = templates.Parse("{{define `driver2`}}Driver 2 calls T2: ({{template `T2`}})\n{{end}}")
    if err != nil {
        log.Fatal("parsing driver2: ", err)
    }
    // We load all the templates before execution. This package does not require
    // that behavior but html/template's escaping does, so it's a good habit.
    err = templates.ExecuteTemplate(os.Stdout, "driver1", nil)
    if err != nil {
        log.Fatalf("driver1 execution: %s", err)
    }
    err = templates.ExecuteTemplate(os.Stdout, "driver2", nil)
    if err != nil {
        log.Fatalf("driver2 execution: %s", err)
    }

    Output:

    Driver 1 calls T1: (T1 invokes T2: (This is T2))
    Driver 2 calls T2: (This is T2)
    
    Example (Share)
    // Here we create a temporary directory and populate it with our sample
    // template definition files; usually the template files would already
    // exist in some location known to the program.
    dir := createTestDir([]templateFile{
        // T0.tmpl is a plain template file that just invokes T1.
        {"T0.tmpl", "T0 ({{.}} version) invokes T1: ({{template `T1`}})\n"},
        // T1.tmpl defines a template, T1 that invokes T2. Note T2 is not defined
        {"T1.tmpl", `{{define "T1"}}T1 invokes T2: ({{template "T2"}}){{end}}`},
    })
    // Clean up after the test; another quirk of running as an example.
    defer os.RemoveAll(dir)
    // pattern is the glob pattern used to find all the template files.
    pattern := filepath.Join(dir, "*.tmpl")
    // Here starts the example proper.
    // Load the drivers.
    drivers := template.Must(template.ParseGlob(pattern))
    // We must define an implementation of the T2 template. First we clone
    // the drivers, then add a definition of T2 to the template name space.
    // 1. Clone the helper set to create a new name space from which to run them.
    first, err := drivers.Clone()
    if err != nil {
        log.Fatal("cloning helpers: ", err)
    }
    // 2. Define T2, version A, and parse it.
    _, err = first.Parse("{{define `T2`}}T2, version A{{end}}")
    if err != nil {
        log.Fatal("parsing T2: ", err)
    }
    // Now repeat the whole thing, using a different version of T2.
    // 1. Clone the drivers.
    second, err := drivers.Clone()
    if err != nil {
        log.Fatal("cloning drivers: ", err)
    }
    // 2. Define T2, version B, and parse it.
    _, err = second.Parse("{{define `T2`}}T2, version B{{end}}")
    if err != nil {
        log.Fatal("parsing T2: ", err)
    }
    // Execute the templates in the reverse order to verify the
    // first is unaffected by the second.
    err = second.ExecuteTemplate(os.Stdout, "T0.tmpl", "second")
    if err != nil {
        log.Fatalf("second execution: %s", err)
    }
    err = first.ExecuteTemplate(os.Stdout, "T0.tmpl", "first")
    if err != nil {
        log.Fatalf("first: execution: %s", err)
    }

    Output:

    T0 (second version) invokes T1: (T1 invokes T2: (T2, version B))
    T0 (first version) invokes T1: (T1 invokes T2: (T2, version A))
    

    func Must

    func Must(t *Template, err error) *Template

    Must函数用于包装返回(*Template, error)的函数/方法调用,它会在err非nil时panic,一般用于变量初始化:

    var t = template.Must(template.New("name").Parse("text"))
    

    func New

    func New(name string) *Template

    创建一个名为name的模板。

    func ParseFiles

    func ParseFiles(filenames ...string) (*Template, error)

    ParseFiles函数创建一个模板并解析filenames指定的文件里的模板定义。返回的模板的名字是第一个文件的文件名(不含扩展名),内容为解析后的第一个文件的内容。至少要提供一个文件。如果发生错误,会停止解析并返回nil。

    func ParseGlob

    func ParseGlob(pattern string) (*Template, error)

    ParseGlob创建一个模板并解析匹配pattern的文件(参见glob规则)里的模板定义。返回的模板的名字是第一个匹配的文件的文件名(不含扩展名),内容为解析后的第一个文件的内容。至少要存在一个匹配的文件。如果发生错误,会停止解析并返回nil。ParseGlob等价于使用匹配pattern的文件的列表为参数调用ParseFiles。

    func (*Template) Name

    func (t *Template) Name() string

    返回模板t的名字。

    func (*Template) Delims

    func (t *Template) Delims(left, right string) *Template

    Delims方法用于设置action的分界字符串,应用于之后的Parse、ParseFiles、ParseGlob方法。嵌套模板定义会继承这种分界符设置。空字符串分界符表示相应的默认分界符:{{或}}。返回值就是t,以便进行链式调用。

    func (*Template) Funcs

    func (t *Template) Funcs(funcMap FuncMap) *Template

    Funcs方法向模板t的函数字典里加入参数funcMap内的键值对。如果funcMap某个键值对的值不是函数类型或者返回值不符合要求会panic。但是,可以对t函数列表的成员进行重写。方法返回t以便进行链式调用。

    func (*Template) Clone

    func (t *Template) Clone() (*Template, error)

    Clone方法返回模板的一个副本,包括所有相关联的模板。模板的底层表示树并未拷贝,而是拷贝了命名空间,因此拷贝调用Parse方法不会修改原模板的命名空间。Clone方法用于准备模板的公用部分,向拷贝中加入其他关联模板后再进行使用。

    func (*Template) Lookup

    func (t *Template) Lookup(name string) *Template

    Lookup方法返回与t关联的名为name的模板,如果没有这个模板返回nil。

    func (*Template) Templates

    func (t *Template) Templates() []*Template

    Templates方法返回与t相关联的模板的切片,包括t自己。

    func (*Template) New

    func (t *Template) New(name string) *Template

    New方法创建一个和t关联的名字为name的模板并返回它。这种可以传递的关联允许一个模板使用template action调用另一个模板。

    func (*Template) AddParseTree

    func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error)

    AddParseTree方法使用name和tree创建一个模板并使它和t相关联。

    func (*Template) Parse

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

    Parse方法将字符串text解析为模板。嵌套定义的模板会关联到最顶层的t。Parse可以多次调用,但只有第一次调用可以包含空格、注释和模板定义之外的文本。如果后面的调用在解析后仍剩余文本会引发错误、返回nil且丢弃剩余文本;如果解析得到的模板已有相关联的同名模板,会覆盖掉原模板。

    func (*Template) ParseFiles

    func (t *Template) ParseFiles(filenames ...string) (*Template, error)

    ParseGlob方法解析filenames指定的文件里的模板定义并将解析结果与t关联。如果发生错误,会停止解析并返回nil,否则返回(t, nil)。至少要提供一个文件。

    func (*Template) ParseGlob

    func (t *Template) ParseGlob(pattern string) (*Template, error)

    ParseFiles方法解析匹配pattern的文件里的模板定义并将解析结果与t关联。如果发生错误,会停止解析并返回nil,否则返回(t, nil)。至少要存在一个匹配的文件。

    func (*Template) Execute

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

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

    func (*Template) ExecuteTemplate

    func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error

    ExecuteTemplate方法类似Execute,但是使用名为name的t关联的模板产生输出。