设为首页 加入收藏

TOP

Go标准库:Go template用法详解(一)
2018-12-02 14:08:56 】 浏览:48
Tags:标准 template 用法 详解

本文只介绍template的语法和用法,关于template包的函数、方法、template的结构和原理,见:深入剖析Go template

入门示例

以下为test.html文件的内容,里面使用了一个template语法{{.}}

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Go Web</title>
    </head>
    <body>
        {{ . }}
    </body>
</html>

以下是test.html同目录下的一个go web程序:

package main

import (
    "html/template"
    "net/http"
)

func tmpl(w http.ResponseWriter, r *http.Request) {
    t1, err := template.ParseFiles("test.html")
    if err != nil {
        panic(err)
    }
    t1.Execute(w, "hello world")
}

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/tmpl", tmpl)
    server.ListenAndServe()
}

前面的html文件中使用了一个template的语法{{.}},这部分是需要通过go的template引擎进行解析,然后替换成对应的内容。

在go程序中,handler函数中使用template.ParseFiles("test.html"),它会自动创建一个模板(关联到变量t1上),并解析一个或多个文本文件(不仅仅是html文件),解析之后就可以使用Execute(w,"hello world")去执行解析后的模板对象,执行过程是合并、替换的过程。例如上面的{{.}}中的.会替换成当前对象"hello world",并和其它纯字符串内容进行合并,最后写入w中,也就是发送到浏览器"hello world"。

本文不解释这些template包的函数、方法以及更底层的理论知识,本文只解释template的语法,如果觉得这些无法理解,或者看不懂官方手册,请看深入剖析Go template

关于点"."和作用域

在写template的时候,会经常用到"."。比如{{.}}{{len .}}{{.Name}}{{$x.Name}}等等。

在template中,点"."代表当前作用域的当前对象。它类似于java/c++的this关键字,类似于perl/python的self。如果了解perl,它更可以简单地理解为默认变量$_

例如,前面示例test.html中{{.}},这个点是顶级作用域范围内的,它代表Execute(w,"hello worold")的第二个参数"hello world"。也就是说它代表这个字符串对象。

再例如,有一个Person struct。

type Person struct {
    Name string
    Age  int
}

func main(){
    p := Person{"longshuai",23}
    tmpl, _ := template.New("test").Parse("Name: {{.Name}}, Age: {{.Age}}")
    _ = tmpl.Execute(os.Stdout, p)
}

这里{{.Name}}{{.Age}}中的点"."代表的是顶级作用域的对象p,所以Execute()方法执行的时候,会将{{.Name}}替换成p.Name,同理{{.Age}}替换成{{p.Age}}

但是并非只有一个顶级作用域,range、with、if等内置action都有自己的本地作用域。它们的用法后文解释,这里仅引入它们的作用域来解释"."。

例如下面的例子,如果看不懂也没关系,只要从中理解"."即可。

package main

import (
    "os"
    "text/template"
)

type Friend struct {
    Fname string
}
type Person struct {
    UserName string
    Emails   []string
    Friends  []*Friend
}

func main() {
    f1 := Friend{Fname: "xiaofang"}
    f2 := Friend{Fname: "wugui"}
    t := template.New("test")
    t = template.Must(t.Parse(
`hello {{.UserName}}!
{{ range .Emails }}
an email {{ . }}
{{- end }}
{{ with .Friends }}
{{- range . }}
my friend name is {{.Fname}}
{{- end }}
{{ end }}`))
    p := Person{UserName: "longshuai",
        Emails:  []string{"a1@qq.com", "a2@gmail.com"},
        Friends: []*Friend{&f1, &f2}}
    t.Execute(os.Stdout, p)
}

输出结果:

hello longshuai!

an email a1@qq.com
an email a2@gmail.com

my friend name is xiaofang
my friend name is wugui

这里定义了一个Person结构,它有两个slice结构的字段。在Parse()方法中:

  • 顶级作用域的{{.UserName}}{{.Emails}}{{.Friends}}中的点都代表Execute()的第二个参数,也就是Person对象p,它们在执行的时候会分别被替换成p.UserName、p.Emails、p.Friends。
  • 因为Emails和Friend字段都是可迭代的,在{{range .Emails}}...{{end}}这一段结构内部an email {{.}},这个"."代表的是range迭代时的每个元素对象,也就是p.Emails这个slice中的每个元素。
  • 同理,with结构内部{{r
    编程开发网
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Go Web:数据存储(1)——内存存储 下一篇Kali Linux搭建Go语言环境

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(214) }