http://golang.org/pkg/text/template/ 与 http://golang.org/pkg/html/template/ 是Go官方的关于 *template*包的文档,——html子包提供了一些附加的安装相关的功能,比如防止代码注入的功能经常在我们的网络编程中被使用。

管道(Pipeline)

Unix 用户肯定是明白什么是 Piping 数据,很多程序都提供字符输出——一个字条流,比如你在终端中键入 ls 命令,你将得到一个包含所有当前目录文件名称的列表,它可以被翻译为:“获取当前目录中所有文件名称的列表,然后通过管道将其传送到标准输出,而当前标准输出为命令行终端的屏幕”。

在Unix命令行终端中,管道“*|*”就可以将你一个命令的输入传送给另一个命令,比如:

cox@Cox:~$ ls | grep "a"
access_log
examples.desktop
goworkspace
VirtualBox VMs
workspace

上面的命令 ls 首先获取当前目录下所有文件的列表,然后再通过管道传递给 grep 命令,grep 从里面搜索包含字符“a”的条目,然后再将过滤后的结果通过管道传递给标准输出,标准输出打印出所有结果,如果你还想再过滤,还可以这样:

cox@Cox:~$ ls | grep "a" | grep "V"
VirtualBox VMs

在Go中,我们也可以将任何一个像上面这样的字符流称之为管道,它们同样可以通过管道传送给其它命令,在下面的示例中,处于 {{ }} 中间的字符串与外面的字符串是不一样的——这些静态文本被无修改的复制到外面。

package main

import (
    "text/template"
    "os"
)

func main() {
    t := template.New("Template Test")
    t = template.Must(t.Parse("This is just static text. n{{"This is pipeline data - because it is evaluated within the double braces."}} {{ `So is this, but within reverse quotes.`}}n"))
    t.Execute(os.Stdout, nil)
}

输出为:

This is just static text.
This is pipeline data - because it is evaluated within the double braces. So is this, but within reverse quotes.

模板中的 if-else-end

在模板中使用 if-else 控制结构与在普通代码中使用差不多,在Go模板中,如果传送数据到if的管道为空,则等同为 false:

package main

import (
    "os"
    "text/template"
)

func main() {
    tEmpty := template.New("template test")
    tEmpty = template.Must(tEmpty.Parse("Empty pipeline if demo: {{if ``}} Will not print. {{ end}}n"))
    tEmpty.Execute(os.Stdout, nil)

    tWithValue := template.New("template test")
    tWithValue = template.Must(tWithValue.Parse("Non empty pipline if demo: {{if `anything`}}  Print If Part.{{ end}}n"))
    tWithValue.Execute(os.Stdout, nil)

    tIfElse := template.New("template test")
    tIfElse = template.Must(tIfElse.Parse("If-else demo:{{if `anything`}} Print IF Part. {{ else }} Else part. {{end}}n"))
    tIfElse.Execute(os.Stdout, nil)
}

输出为:

Empty pipeline if demo:
Non empty pipline if demo:   Print If Part.
If-else demo: Print IF Part.

点(*.*)

在Go模板中,点(.)被用来引用当前的管道,你可以想像成为这个点是 Java 中的 this 或者我们在Python中最常使用的 *self*,你可以使用 *{{.}}*引用到它的值。

with-end 结构

with 声明用来设置 点(.) 在管道中的数据:

package main

import (
    "os"
    "text/template"
    )

func main() {
    t, _ := template.New("test").Parse("{{with `hello`}}{{.}}{{end}}!n")
    t.Execute(os.Stdout, nil)

    t1, _ := template.New("test").Parse("{{with `hello`}}{{.}} {{with `Mary`}}{{.}}{{end}}{{end}}!n") //when nested, the dot takes the value according to closest scope.
    t1.Execute(os.Stdout, nil)
}

输出为:

hello!
hello Mary!

模板变量

你可以在模板管道中使用*$*前缀创建本地变量,变量名称必须为英文字母、数字以及下划线:

package main

import (
    "os"
    "text/template"
)

func main() {
    t := template.Must(template.New("name").Parse("{{with $3 := `hello`}}{{$3}}{{end}}!n"))
    t.Execute(os.Stdout, nil)

    t1 := template.Must(template.New("name1").Parse("{{with $x3 := `hola`}}{{$x3}}{{end}}!n"))
    t1.Execute(os.Stdout, nil)

    t2 := template.Must(template.New("name2").Parse("{{with $x_1 := `hey`}}{{$x_1}} {{.}} {{$x_1}}{{end}}!n"))
    t2.Execute(os.Stdout, nil)
}

被重新定义的函数

Go模板同样还提供了一些被重新定义了的函数,比如下面这个示例的 printf 就与 fmt.Sprintf 类似:

package main

import (
    "os"
    "text/template"
)

func main() {
    t := template.New("test")
    t = template.Must(t.Parse("{{with $x := `hello`}}{{printf `%s %s` $x `Mary`}}{{end}}!n"))
    t.Execute(os.Stdout, nil)
}

输出为:

hello Mary!

标签: none

评论已关闭