template intro

Go的模板简介,基于1.9.2,具体细节还请参考godoc。

1. Overview
模板是含特定标签的字符串文本,按照固定语法将它解析为静态内存结构。该结构 + 输入数据对象 => 模板执行结果。

模板字符串是UTF-8。“Action”-数据和控制结构-以“{{”和“}}”分隔;action之外的文本原封不动输出。举例:
//struct 是输入数据对象
type Inventory struct {
	Material string
	Count    uint
}
sweaters := Inventory{"wool", 17}
//模板对象
tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
if err != nil { panic(err) }
//执行({{.XX}}对应sweaters.XX)
err = tmpl.Execute(os.Stdout, sweaters)
if err != nil { panic(err) }


1.1 Action
下面是所有action。

{{/* a comment */}}
    注释
{{pipeline}}
    pipeline用于计算数据。输出其文本表示(同fmt.Print)
{{if pipeline}} T1 {{end}}
    pipeline empty跳过;否则执行T1。empty指false|0|nil、或长度=0的array|slice|map|string。
{{if pipeline}} T1 {{else}} T0 {{end}}
    not empty T1,否则T0
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
{{range pipeline}} T1 {{end}}
    pipeline的值应是array|slice|map|channel,遍历它的每个元素每次执行T1。pipeline长度=0时没有输出。
{{range pipeline}} T1 {{else}} T0 {{end}}
    T0在pipeline长度=0时执行
{{template "name"}}
    执行名称="name"的模板,输入数据=nil。注:一个模板可以关联多个模板(例如page header、page footer也是模板,嵌在大页面模板里 - 它们定义在一个字符串文本里)
{{template "name" pipeline}}
    执行且输入数据=pipeline
{{block "name" pipeline}} T1 {{end}}
    相当于定义"name"模板并马上执行它。注-定义模板:
        {{define "name"}} T1 {{end}}
{{with pipeline}} T1 {{end}}
    设置输入数据=pipeline,执行T1。如果pipeline empty,没有输出。
{{with pipeline}} T1 {{else}} T0 {{end}}

1.2 Argument
Argument是个简单值:
-boolean, string, character, integer, floating-point, imaginary or complex constant
-nil
-'.'(点号):当前数据(注:模板开始执行时当前数据=输入数据;遍历array时循环体内当前数据=array的当前元素,类推)
-变量名(以$开头),如“$piOver2”、“$”:该变量的值
-当前数据的某字段:.Field。可以嵌套:.Field1.Field2。也可以是变量的字段:$x.Field1.Field2
-当前数据是map时:.Key 取该key的值。可以嵌套:.Field1.Key1.Field2.Key2。也可以用于变量:$x.key1.key2
-调用当前数据的某方法:.Method - 方法需要有返回值。可以嵌套:.Field1.Key1.Method1.Field2.Key2.Method2。同样也可以用于变量
-函数调用:fun
-括号分隔如:(.StructValuedMethod "arg").Field

1.3 Pipeline
Pipeline是单个command或嵌套的一组command。Command是一个简单值(argument)、或一个函数|方法调用(可能有多个参数):
-Argument
-.Method [Argument...]
  在当前数据上调用此方法:当前数据.Method(Argument1, etc.)。只有在嵌套链的末尾或单独使用时才能带参数
-functionName [Argument...]
  调用该函数

在两个commands之间使用“|”做管道:前一个command的结果将作为后一个command的最后一个参数,如此嵌套。最后一个command的结果=该pipeline的结果。

1.4 Variable
定义并初始化一个变量:“$variable := pipeline”。
遍历时:“range $index, $element := pipeline”。
变量的作用域(scope)止于所在的if|with|range action,或模板结尾。

1.5 举例
以下所有例子均输出被引号包围的字符串output:

{{"\"output\""}}
    string常量
{{`"output"`}}
    raw string常量
{{printf "%q" "output"}}
    函数调用
{{"output" | printf "%q"}}
    printf函数的第二个参数来自前面command
{{printf "%q" (print "out" "put")}}
    括号
{{"put" | printf "%s%s" "out" | printf "%q"}}
{{"output" | printf "%s" | printf "%q"}}
{{with "output"}}{{printf "%q" .}}{{end}}
    在with action里,"."(当前数据)="output"
{{with $x := "output" | printf "%q"}}{{$x}}{{end}}
    pipeline = “$x := "output" | printf "%q"”
{{with $x := "output"}}{{printf "%q" $x}}{{end}}
{{with $x := "output"}}{{$x | printf "%q"}}{{end}}

1.6 Function
函数来自于a)通过template.Funcs方法添加的、b)全局函数。

预定义的全局函数:
-and
  返回第一个empty的argument、或最后一个argument。如“and x y”=“if x then y else x”。注意:由于是函数调用,所有argument都会被计算。
-call
  函数调用,第一个参数代表一个函数,其余参数是该函数的调用参数。例如“.X.Y 1 2”:当前数据.X.Y应该=一个函数(例如map X.Y元素=函数、struct X.Y字段=函数)。
-html
  参数的escaped HTML
-index
  如“index x 1 2 3”=“x[1][2][3]”
-js
  参数的escaped JavaScript
-len
  参数的长度
-not
  唯一参数的boolean 非
-or
  返回第一个not empty的argument、或最后一个argument。如“or x y”=“if x then x else y”。同样,所有argument都会被计算
-print
  fmt.Sprint
-printf
  fmt.Sprintf
-println
  fmt.Sprintln
-urlquery
  参数escaped,用于URL query

boolean函数里零值(zero value)为false,非零值为true。

一组二元比较运算符:
-eq
  arg1 == arg2
-ne
-lt
  arg1 < arg2
-le
   arg1 <= arg2
-gt
-ge

多个参数的eq比较相当于“arg1==arg2 || arg1==arg3 || arg1==arg4 ...”。例如模板
“{{if eq 123 13 2 456 123}}equals{{else}} not equals{{end}}”执行结果是“equals”。同样注意:eq是函数调用,所以每个argument都会被计算。
不能比较不同的基本类型,例如int和string无法比较。

1.7 关联模板
模板创建时要指定名称。一个模板可以再关联多个模板 - 这种关联是可传递的,形成了名称空间(TODO)。

1.8 嵌套模板定义
模板的字符串文本里可以定义多个模板。它们必须定义在顶层,以“define”和“end” action分隔。例如:
{{define "T1"}}ONE{{end}}
{{define "T2"}}TWO{{end}}
{{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
{{template "T3"}}

里面还定义了T1、T2、T3三个模板。该模板执行时会执行T3 - T3执行时会执行T1和T2。该模板执行输出:
ONE TWO


一个模板只能存在于一个关联中。如果要从多个关联里存取同一个模板,只能构造多个该模板对象、或者调用Clone方法(TODO)。

用Execute方法执行模板,或用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)
}


2. Index
TODO

猜你喜欢

转载自pelli.iteye.com/blog/2399729