Golang标准库——text

DevilRoshan · · 959 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  • scanner
  • tabwriter
  • template
  • template/parse

scanner

scanner包提供对utf-8文本的token扫描服务。它会从一个io.Reader获取utf-8文本,通过对Scan方法的重复调用获取一个个token。为了兼容已有的工具,NUL字符不被接受。如果第一个字符是表示utf-8编码格式的BOM标记,会自动忽略该标记。

一般Scanner会跳过空白和Go注释,并会识别所有go语言规格的字面量。它可以定制为只识别这些字面量的一个子集,也可以识别不同的空白字符。

基本使用模式:

var s scanner.Scanner
s.Init(src)
tok := s.Scan()
for tok != scanner.EOF {
    // do something with tok
    tok = s.Scan()
}

Constants

const (
    ScanIdents     = 1 << -Ident
    ScanInts       = 1 << -Int
    ScanFloats     = 1 << -Float // 包括整数
    ScanChars      = 1 << -Char
    ScanStrings    = 1 << -String
    ScanRawStrings = 1 << -RawString
    ScanComments   = 1 << -Comment
    SkipComments   = 1 << -skipComment // 如设置了ScanComments就视注释为空白
    GoTokens       = ScanIdents | ScanFloats | ScanChars
                   | ScanStrings | ScanRawStrings | ScanComments | SkipComments
)

预定义的状态位,用于控制token的识别。例如,如要设置Scanner只识别标识符、整数、跳过注释,可以将Scanner的状态字段设为:

ScanIdents | ScanInts | SkipComments
const (
    EOF = -(iota + 1)
    Ident
    Int
    Float
    Char
    String
    RawString
    Comment
)

扫描的结果是上面的一个token或者一个Unicode字符。

const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

GoWhitespace是一个Scanner的Whitespace字段的默认值,该值确定go的空白字符。

func TokenString

func TokenString(tok rune) string

TokenString返回一个token或unicode码值的可打印的字符串表示。

type Position

type Position struct {
    Filename string // 文件名(如果存在)
    Offset   int    // 偏移量,从0开始
    Line     int    // 行号,从1开始
    Column   int    // 列号,从1开始(每行第几个字符)
}

代表资源里的一个位置。

func (*Position) IsValid

func (pos *Position) IsValid() bool

IsValid返回所处的位置是否合法。

func (Position) String

func (pos Position) String() string

type Scanner

type Scanner struct {
    // 每一次出现错误时都会调用该函数;如果Error为nil,则会将错误报告到os.Stderr。
    Error func(s *Scanner, msg string)
    // 每一次出现错误时,ErrorCount++
    ErrorCount int
    // 控制那些token被识别。如要识别整数,就将Mode的ScanInts位设为1。随时都可以修改Mode。
    Mode uint
    // 控制那些字符识别为空白。如果要将一个码值小于32的字符视为空白,只需将码值对应的位设为1;
    // 空格码值是32,大于32的位设为1的行为未定义。随时都可以修改Whitespace。
    Whitespace uint64
    // 最近一次扫描到的token的开始位置,由Scan方法设定
    // 调用Init或Next方法会使位置无效(Line==0),Scanner不会操作Position.Filename字段
    // 如果发生错误且Position不合法,此时扫描位置不在token内,应调用Pos获取错误发生的位置
    Position
    // 内含隐藏或非导出字段
}

Scanner类型实现了token和unicode字符(从io.Reader中)的读取。

func (*Scanner) Init

func (s *Scanner) Init(src io.Reader) *Scanner

Init使用src创建一个Scanner,并将Error设为nil,ErrorCount设为0,Mode设为GoTokens,Whitespace 设为GoWhitespace。

func (*Scanner) Pos

func (s *Scanner) Pos() (pos Position)

Pos方法返回上一次调用Next或Scan方法后读取结束时的位置。

func (*Scanner) Peek

func (s *Scanner) Peek() rune

Peek方法返回资源的下一个unicode字符而不移动扫描位置。如果扫描位置在资源的结尾会返回EOF。

func (*Scanner) Next

func (s *Scanner) Next() rune

Next读取并返回下一个unicode字符。到达资源结尾时会返回EOF。如果s.Error非nil,本方法会调用该字段汇报错误;否则将错误信息发送到os.Stderr。Next不会更新Scanner的Position字段,请使用Pos方法获取当前位置。

func (*Scanner) Scan

func (s *Scanner) Scan() rune

Scan方法从资源读取下一个token或者unicode字符并返回它。本方法只会识别Mode字段指定的token种类。如果到达资源结尾会返回EOF。如果s.Error非nil,本方法会调用该字段汇报错误;否则将错误信息发送到os.Stderr。

func (*Scanner) TokenText

func (s *Scanner) TokenText() string

TokenText方法返回最近一次扫描的token对应的字符串。应该在Scan方法后调用。

tabwriter

tabwriter包实现了写入过滤器(tabwriter.Writer),可以将输入的缩进修正为正确的对齐文本。

本包采用的Elastic Tabstops算法参见http://nickgravgaard.com/elastictabstops/index.html

Constants

const (
    // 忽略html标签,并将字符实体(以'&'开始,以';'结束)视为单字符
    FilterHTML uint = 1 << iota
    // 将转义后文本两端的转义字符去掉
    StripEscape
    // 强制单元格右对齐,默认是左对齐的
    AlignRight
    // 剔除空行
    DiscardEmptyColumns
    // 使用tab而不是空格进行缩进
    TabIndent
    // 在格式化后在每一列两侧添加'|'并忽略空行
    Debug
)

这些标志用于控制格式化。

const Escape = '\xff'

用于包围转义字符,避免该字符被转义;例如字符串"Ignore this tab: \xff\t\xff"中的'\t'不被转义,不结束单元;格式化时Escape视为长度1的单字符。

选择'\xff'是因为该字符不能出现在合法的utf-8序列里。

type Writer

type Writer struct {
    // 内含隐藏或非导出字段
}

Writer是一个过滤器,会在输入的tab划分的列进行填充,在输出中对齐它们。

它会将输入的序列视为utf-8编码的文本,包含一系列被垂直制表符、水平制表符、换行符、回车符分割的单元。临近的单元组成一列,根据需要填充空格使所有的单元有相同的宽度,高效对齐各列。它假设所有的字符都有相同的宽度,除了tab,tab宽度应该被指定。注意单元以tab截止,而不是被tab分隔,行最后的非tab文本不被视为列的单元。

Writer假设所有的unicode字符有着同样的宽度,这一点其实在很多字体里是错误的。

如果设置了DiscardEmptyColumns,以垂直制表符结尾的空列会被丢弃,水平制表符截止的空列则不会被影响。

如果设置了FilterHTML,HTML标签和实体会被放过,标签宽度视为0,实体宽度视为1。文本段可能被转义字符包围,此时tabwriter不会修改该文本段,不会打断段中的任何tab或换行。

如果设置了StripEscape,则不会计算转义字符的宽度(输出中也会去除转义字符)。

进纸符'\f'被视为换行,但也会截止当前行的所有列(有效的刷新);除非在HTML标签内或者在转义文本段内,输出中'\f'都被作为换行。

Writer会在内部缓存输入以便有效的对齐,调用者必须在写完后执行Flush方法。

func NewWriter

func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer

创建并初始化一个tabwriter.Writer,参数用法和Init函数类似。

func (*Writer) Init

func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer

初始化一个Writer,第一个参数指定格式化后的输出目标,其余的参数控制格式化:

minwidth 最小单元长度
tabwidth tab字符的宽度
padding  计算单元宽度时会额外加上它
padchar  用于填充的ASCII字符,
         如果是'\t',则Writer会假设tabwidth作为输出中tab的宽度,且单元必然左对齐。
flags    格式化控制

func (*Writer) Write

func (b *Writer) Write(buf []byte) (n int, err error)

将buf写入b,实现io.Writer接口,只有在写入底层输出流是才可能发生并返回错误。

func (*Writer) Flush

func (b *Writer) Flush() (err error)

在最后一次调用Write后,必须调用Flush方法以清空缓存,并将格式化对齐后的文本写入生成时提供的output中。

func main() {
   w := new(tabwriter.Writer)
   // Format in tab-separated columns with a tab stop of 8.
   w.Init(os.Stdout, 0, 8, 0, '\t', 0)
   fmt.Fprintln(w, "a\tb\tc\td\t.")
   fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
   fmt.Fprintln(w)
   w.Flush()
   // Format right-aligned in space-separated columns of minimal width 5
   // and at least one blank of padding (so wider column entries do not
   // touch each other).
   w.Init(os.Stdout, 5, 0, 1, ' ', tabwriter.AlignRight)
   fmt.Fprintln(w, "a\tb\tc\td\t.")
   fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
   fmt.Fprintln(w)
   w.Flush()
}

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

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包使用的,因此其他人应该视字段未导出。

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关联的模板产生输出。

template/parse

parse包为text / template和html / template定义的模板构建解析树。 客户应使用这些软件包来构造模板,而不要使用该模板,后者可以提供不用于一般用途的共享内部数据结构。

func IsEmptyTree

func IsEmptyTree(n Node) bool

IsEmptyTree报告此树(节点)是否除空间外什么都没有。

func Parse

func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (map[string]*Tree, error)

Parse返回从模板名称到parse.Tree的映射,该映射是通过解析参数字符串中描述的模板而创建的。 将为顶层模板指定名称。 如果遇到错误,解析将停止,并返回带有错误的空映射。

type ActionNode

type ActionNode struct {
    NodeType
    Pos

    Line int       // The line number in the input. Deprecated: Kept for compatibility.
    Pipe *PipeNode // The pipeline in the action.
    // contains filtered or unexported fields
}

ActionNode持有一个动作(由定界符限制)。 控制动作具有自己的节点; ActionNode代表简单的变量,例如字段评估和带括号的管道。

func (*ActionNode) Copy

func (a *ActionNode) Copy() Node

func (*ActionNode) String

func (a *ActionNode) String() string

type BoolNode

type BoolNode struct {
    NodeType
    Pos

    True bool // The value of the boolean constant.
    // contains filtered or unexported fields
}

BoolNode拥有一个布尔常量。

func (*BoolNode) Copy

func (b *BoolNode) Copy() Node

func (*BoolNode) String

func (b *BoolNode) String() string

type BranchNode

type BranchNode struct {
    NodeType
    Pos

    Line     int       // The line number in the input. Deprecated: Kept for compatibility.
    Pipe     *PipeNode // The pipeline to be evaluated.
    List     *ListNode // What to execute if the value is non-empty.
    ElseList *ListNode // What to execute if the value is empty (nil if absent).
    // contains filtered or unexported fields
}

BranchNode是if,range和with的通用表示形式。

func (*BranchNode) Copy

func (b *BranchNode) Copy() Node

func (*BranchNode) String

func (b *BranchNode) String() string

type ChainNode

type ChainNode struct {
    NodeType
    Pos

    Node  Node
    Field []string // The identifiers in lexical order.
    // contains filtered or unexported fields
}

ChainNode持有一个术语,后跟一连串的字段访问(以“。”开头的标识符)。 名称可以链接(“ .x.y”)。 期间从每个标识中删除。

func (*ChainNode) Add

func (c *ChainNode) Add(field string)

Add将命名字段(应以句点开头)添加到链的末尾。

func (*ChainNode) Copy

func (c *ChainNode) Copy() Node

func (*ChainNode) String

func (c *ChainNode) String() string

type CommandNode

type CommandNode struct {
    NodeType
    Pos

    Args []Node // Arguments in lexical order: Identifier, field, or constant.
    // contains filtered or unexported fields
}

CommandNode保留命令(评估动作内部的管道)。

func (*CommandNode) Copy

func (c *CommandNode) Copy() Node

func (*CommandNode) String

func (c *CommandNode) String() string

type DotNode

type DotNode struct {
    NodeType
    Pos
    // contains filtered or unexported fields
}

DotNode保留特殊标识符“.”。

func (*DotNode) Copy

func (d *DotNode) Copy() Node

func (*DotNode) String

func (d *DotNode) String() string

func (*DotNode) Type

func (d *DotNode) Type() NodeType

type FieldNode

type FieldNode struct {
    NodeType
    Pos

    Ident []string // The identifiers in lexical order.
    // contains filtered or unexported fields
}

FieldNode保存一个字段(以“.”开头的标识符)。 名称可以链接(“ .x.y”)。 该期间从每个标识中删除。

func (*FieldNode) Copy

func (f *FieldNode) Copy() Node

func (*FieldNode) String

func (f *FieldNode) String() string

type IdentifierNode

type IdentifierNode struct {
    NodeType
    Pos

    Ident string // The identifier's name.
    // contains filtered or unexported fields
}

IdentifierNode包含一个标识符。

func NewIdentifier

func NewIdentifier(ident string) *IdentifierNode

NewIdentifier返回具有给定标识符名称的新IdentifierNode。

func (*IdentifierNode) Copy

func (i *IdentifierNode) Copy() Node

func (*IdentifierNode) SetPos

func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode

SetPos设置位置。 NewIdentifier是一个公共方法,因此我们无法修改其签名。 链接起来很方便。

func (*IdentifierNode) SetTree

func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode

SetTree设置节点的父树。 NewIdentifier是一个公共方法,因此我们无法修改其签名。 链接起来很方便。

func (*IdentifierNode) String

func (i *IdentifierNode) String() string

type IfNode

type IfNode struct {
    BranchNode
}

IfNode表示一个{{if}}动作及其命令。

func (*IfNode) Copy

func (i *IfNode) Copy() Node

type ListNode

type ListNode struct {
    NodeType
    Pos

    Nodes []Node // The element nodes in lexical order.
    // contains filtered or unexported fields
}

ListNode包含一系列节点。

func (*ListNode) Copy

func (l *ListNode) Copy() Node

func (*ListNode) CopyList

func (l *ListNode) CopyList() *ListNode

func (*ListNode) String

func (l *ListNode) String() string

type NilNode

type NilNode struct {
    NodeType
    Pos
    // contains filtered or unexported fields
}

NilNode保留特殊标识符“ nil”,该标识符表示未类型化的nil常数。

func (*NilNode) Copy

func (n *NilNode) Copy() Node

func (*NilNode) String

func (n *NilNode) String() string

func (*NilNode) Type

func (n *NilNode) Type() NodeType

type Node

type Node interface {
    Type() NodeType
    String() string
    // Copy does a deep copy of the Node and all its components.
    // To avoid type assertions, some XxxNodes also have specialized
    // CopyXxx methods that return *XxxNode.
    Copy() Node
    Position() Pos // byte position of start of node in full original input string
    // contains filtered or unexported methods
}

节点是解析树中的元素。 该接口是微不足道的。 接口包含一个未导出的方法,因此只有此程序包本地的类型才能满足它。

type NodeType

type NodeType int

NodeType标识解析树节点的类型。

const (
    NodeText    NodeType = iota // Plain text.
    NodeAction                  // A non-control action such as a field evaluation.
    NodeBool                    // A boolean constant.
    NodeChain                   // A sequence of field accesses.
    NodeCommand                 // An element of a pipeline.
    NodeDot                     // The cursor, dot.

    NodeField      // A field or method name.
    NodeIdentifier // An identifier; always a function name.
    NodeIf         // An if action.
    NodeList       // A list of Nodes.
    NodeNil        // An untyped nil constant.
    NodeNumber     // A numerical constant.
    NodePipe       // A pipeline of commands.
    NodeRange      // A range action.
    NodeString     // A string constant.
    NodeTemplate   // A template invocation action.
    NodeVariable   // A $ variable.
    NodeWith       // A with action.
)

func (NodeType) Type

func (t NodeType) Type() NodeType

类型返回自身,并提供一个简单的默认实现以嵌入到Node中。 嵌入所有非平凡节点中。

type NumberNode

type NumberNode struct {
    NodeType
    Pos

    IsInt      bool       // Number has an integral value.
    IsUint     bool       // Number has an unsigned integral value.
    IsFloat    bool       // Number has a floating-point value.
    IsComplex  bool       // Number is complex.
    Int64      int64      // The signed integer value.
    Uint64     uint64     // The unsigned integer value.
    Float64    float64    // The floating-point value.
    Complex128 complex128 // The complex value.
    Text       string     // The original textual representation from the input.
    // contains filtered or unexported fields
}

NumberNode拥有一个数字:有符号或无符号整数,浮点数或复数。 解析该值并将其存储在可以代表该值的所有类型下。 这用少量的代码模拟了Go的理想常数的行为。

func (*NumberNode) Copy

func (n *NumberNode) Copy() Node

func (*NumberNode) String

func (n *NumberNode) String() string

type PipeNode

type PipeNode struct {
    NodeType
    Pos

    Line int             // The line number in the input. Deprecated: Kept for compatibility.
    Decl []*VariableNode // Variable declarations in lexical order.
    Cmds []*CommandNode  // The commands in lexical order.
    // contains filtered or unexported fields
}

PipeNode使用可选声明保存管道

func (*PipeNode) Copy

func (p *PipeNode) Copy() Node

func (*PipeNode) CopyPipe

func (p *PipeNode) CopyPipe() *PipeNode

func (*PipeNode) String

func (p *PipeNode) String() string

type Pos

type Pos int

Pos表示原始输入文本中从中解析此模板的字节位置。

func (Pos) Position

func (p Pos) Position() Pos

type RangeNode

type RangeNode struct {
    BranchNode
}

RangeNode表示{{range}}动作及其命令。

func (*RangeNode) Copy

func (r *RangeNode) Copy() Node

type StringNode

type StringNode struct {
    NodeType
    Pos

    Quoted string // The original text of the string, with quotes.
    Text   string // The string, after quote processing.
    // contains filtered or unexported fields
}

StringNode保存一个字符串常量。 该值已被“取消引用”。

func (*StringNode) Copy

func (s *StringNode) Copy() Node

func (*StringNode) String

func (s *StringNode) String() string

type TemplateNode

type TemplateNode struct {
    NodeType
    Pos

    Line int       // The line number in the input. Deprecated: Kept for compatibility.
    Name string    // The name of the template (unquoted).
    Pipe *PipeNode // The command to evaluate as dot for the template.
    // contains filtered or unexported fields
}

TemplateNode代表一个{{template}}动作。

func (*TemplateNode) Copy

func (t *TemplateNode) Copy() Node

func (*TemplateNode) String

func (t *TemplateNode) String() string

type TextNode

type TextNode struct {
    NodeType
    Pos

    Text []byte // The text; may span newlines.
    // contains filtered or unexported fields
}

TextNode保存纯文本。

func (*TextNode) Copy

func (t *TextNode) Copy() Node

func (*TextNode) String

func (t *TextNode) String() string

type Tree

type Tree struct {
    Name      string    // name of the template represented by the tree.
    ParseName string    // name of the top-level template during parsing, for error messages.
    Root      *ListNode // top-level root of the tree.
    // contains filtered or unexported fields
}

Tree是单个已解析模板的表示。

func New

func New(name string, funcs ...map[string]interface{}) *Tree

New使用给定名称分配新的解析树。

func (*Tree) Copy

func (t *Tree) Copy() *Tree

复制返回树的副本。 任何解析状态都将被丢弃。

func (*Tree) ErrorContext

func (t *Tree) ErrorContext(n Node) (location, context string)

ErrorContext返回输入文本中节点位置的文本表示形式。 仅当节点内部没有指向树的指针时才使用接收器,这可能会在旧代码中出现。

func (*Tree) Parse

func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error)

解析解析模板定义字符串,以构造要执行的模板的表示形式。 如果任何一个动作分隔符字符串为空,则使用默认值(“ {{”或“}}”)。 嵌入式模板定义将添加到treeSet映射中。

type VariableNode

type VariableNode struct {
    NodeType
    Pos

    Ident []string // Variable name and fields in lexical order.
    // contains filtered or unexported fields
}

VariableNode包含变量名列表,可能具有链接的字段访问。 美元符号是(名字)名称的一部分。

func (*VariableNode) Copy

func (v *VariableNode) Copy() Node

func (*VariableNode) String

func (v *VariableNode) String() string

type WithNode

type WithNode struct {
    BranchNode
}

WithNode代表{{with}}动作及其命令。

func (*WithNode) Copy

func (w *WithNode) Copy() Node

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:DevilRoshan

查看原文:Golang标准库——text

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

959 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传