26

Golang标准库——text

 4 years ago
source link: https://studygolang.com/articles/31274
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
  • 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

这时, FRjae2a.png!mobile 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

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK