加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Go 语言的Template Package

发布时间:2020-12-16 18:09:15 所属栏目:大数据 来源:网络整理
导读:理解template package之前,最好能快速看一下Go的一些数据结构,比如struct,array 和slice,这些数据结构在template 里面会被经常用到。 Struct struct是一个包含多个field的集合,跟C语言的结构体非常类似,可以用关键字type以及struct来定义一个struct。例

理解template package之前,最好能快速看一下Go的一些数据结构,比如struct,array 和slice,这些数据结构在template 里面会被经常用到。

Struct

struct是一个包含多个field的集合,跟C语言的结构体非常类似,可以用关键字type以及struct来定义一个struct。例如:

type My_Struct_Name struct { X int Y string }

注意上面的定义的struct在当前这个package外面也是可见的,因为它的名字是以大写字母开头的。变量X和Y同样也是包外面可见的,因为它们都是大写字母开头的。可以通过.+field的名字来访问Struct里面定义的fields,比如:

msn := My_Struct_Name{1,"talim"}
msn.X = 4

若通过变量名可以以任何顺序初始化这个Struct,如下:

msn2 := My_Struct_Name{Y: “Talim”,X: 15} 

Array

Go语言的数组是一个包含指定数量元素的数列。
在下面的代码片断中,我们创建一个名字为”arr”的数组,它包含了5个int类型的整数,元素的类型及长度就是数据的类型和长度。默认数组里面元素的值是0。

var arr [5]int

我们可以通过数组的下标来给一个元素赋值,语法是“array[index] = value”,也可以通过下标来取值。
下面的语法中我们可以通过一行代码来声明和初始化一个数组:

arr2 := [5]int{1,2,3,4,5}

Slice

slice是数组的一个segment(片段), 跟数组一样,slice可以通过下标来存取,同时也有长度。跟数组不一样的是,slice的长度是可变的。下面就是一个slice的一个例子:

var x []int

这个跟数组唯一不一样的就是没有在[]之间给定长度。上面就创建一个长度为0的x变量。
如果你要创建一个slice,你可以调用内置函数”make”:

x := make([]int, 5)

这样就创建一个slice,它会跟一个长度为5的数组关联起来。Slices总是跟数组相关联的,它必须小于数组的长度。

text/template

用法:

import “text/template

很多服务器端的语言都提供一种机制来定义一些静态的页面,然后往里面插入动态生成的组件,比如插入一个列表。典型的例子JSP/PHP里面的脚本。GO在template这个package也提供了类似的相关的脚本语言。

这个包以文本作为输入,基于对对象值的解释,把原来的输入文本转换成其它的不一样的文本。

为了生成HTML格式的文本,我们可以很快去学习关于”html/template”的package,它提供了跟text/template相同的接口,但可以自动使输出的HTML免于某些攻击。

template会作用在一个Go object上。Go object里面的field可以被插入到template,你也可以挖掘这个object来得到它所有的field,等等。可以用”.“来代表当前这个object, 因此如果想把这个object的值作为String插入到template,你可以这样用”{{.}}“。package默认会使用”fmt”这个package来生成字符串作为插入到template的值。

如果只是想把当前object的一个field的值插入到template,你可以通过在这个field的名字前面加一个前缀 “.”。 假设我们定义这样一个类型的对象:

type Student struct { Name string }

然后你就可以通过下面的方式插入Name的值:

The name is {{.Name}}.

所以template是一种将通用文本(不会变化的)跟特定文本作merge的方法,例如tempate可以保留里面通用的文本,然后根据需要替换一些特定的文本。

这种定义的语法就是把template的声明用“define”“end” action包起来。

define这个action后面跟着一个字符串来指定template的名字
,下面就是一个例子:

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

这里定义了两个template,T1和T2,第三个T3执行时会调用了其它两个template。最后调用T3。如果运行T3这个template,它会输出下面的文本:

ONE TWO

在Go语言中,我们用template这个package以及它的”Parse”, “ParseFile”, “Execute”之类的方法来从字符串或者文件中加载一个template,然后做上面提到的文本的转换和merge。 需要merge的内容通常在一个自定义的类型里面,这个类型包含一些可以被外面的包访问的field,例如template用到的一些定义在struct这个类型里面的filed就需要以大写字母开头。

让我们看一个简单的例子。

创建下面一个目录并且切换到这个目录:

$ mkdir $GOPATH/src/github.com/SatishTalim/texttmpl
$ cd $GOPATH/src/github.com/SatishTalim/texttmpl

在这个目录下面写个名字叫”stud_struct.go”的程序,如下:

package main

import (
        "log"
        "os"
        "text/template"
)

type Student struct {
        //exported field since it begins
        //with a capital letter
        Name string
}

func main() {
        //define an instance
        s := Student{"Satish"}

        //create a new template with some name
        tmpl := template.New("test")

        //parse some content and generate a template
        tmpl,err := tmpl.Parse("Hello {{.Name}}!")
        if err != nil {
                log.Fatal("Parse: ",err)
                return
        }

        //merge template 'tmpl' with content of 's'
        err1 := tmpl.Execute(os.Stdout,s)
        if err1 != nil {
                log.Fatal("Execute: ",err1)
                return
        }
}

你可以敲如下的命令来执行这个程序:

$ go run stud_struct.go

输出结果:

Hello Satish!

注意:

  • “New”关键字创建了一个指定名字的新template。
  • “Parse”将一个字符串解释成template
  • 要将某个field的内容放到template里面,就将这个field用大括号包起来,并且在这个field的前面加一个点号。例如,如果Name 是某个struct的一个field,并且在merge的时候需要将它的值替换进去,则需要把“{{.Name}}”放到template。但要记住这个field必需是存在的并且它是对外可见的(在类型定义中以大写字母开头),否则会报错。所有”{{.Name}}”外面的文本会被原封不动地拷贝到输出的文本中。
  • 我们这里用预先定义好的变量”os.Stdout”来将merge之后的文本输出到标准输出设备中 - “os.Stdout” 实现了”io.Writer”
  • “Execute”方法将一个已经加载的模板应用到指定的数据object上,并且将输出到”os.Stdout”

让我们看另外一个例子。

创建下面一个目录并且切换到这个目录:

$ mkdir $GOPATH/src/github.com/SatishTalim/person
$ cd $GOPATH/src/github.com/SatishTalim/person

在这个目录下写一个”person.go”的程序:

package main

import (
        "log"
        "os"
        "text/template"
)

type Person struct {
        Name   string
        Emails []string
}

const tmpl = `The name is {{.Name}}.
{{range .Emails}}
    His email id is {{.}}
{{end}}
`

func main() {
        person := Person{
                Name:   "Satish",Emails: []string{"satish@rubylearning.org","satishtalim@gmail.com"},}

        t := template.New("Person template")

        t,err := t.Parse(tmpl)
        if err != nil {
                log.Fatal("Parse: ",err)
                return
        }

        err = t.Execute(os.Stdout,person)
        if err != nil {
                log.Fatal("Execute: ",err)
                return
        }
}

敲入如下命令来运行这个程序:

$ go run person.go

输出结果:

The name is Satish.
    His email id is satish@rubylearning.org
    His email id is satishtalim@gmail.com

Go的template package在文本转换时非常有用,特别是当这个转换需要插入对象的值时。它虽没有正则表达式那么强大,但却更快并且很多情况下比正则表达式好用。

html/template

Usage:

import “html/template

“html/template”这个包实现了data-driven template,用来生成HTML输出,比直接的代码注入更安全。它提供了跟”text/template”一样的接口,当输出的格式是HTML是应该用”html/template”这个package,而不是”text/template”。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读