PHP页面中嵌套go语言,Go 模板嵌套最佳实践

Go 官方库提供了两个模板库:text/template和html/template。这两个库类似,只不过html/template对html格式做了特别的处理,当需要输出html格式的代码时需要使用html/template。

使用模版,可以帮助我们写一些通用的代码,或者提供清晰的文件布局, 或者提供一个代码生成器。

官方文档提供了很好的模版的使用方法, 其中text/template提供了基础的模版的使用方法,比如

Action、 Argument、Pipeline、Variable、Function、模版嵌套的介绍,html/template对

Context 进行了介绍。 本文假定你已经了解了这些基础知识。如果你还不清楚,或者还没有用过模版,可以参考文末的参考文档进行学习。

虽然text/template官方文档对模版嵌套简单了介绍,但是对于如何使用嵌套模版进行实际开发,以及注意事项并没有详细的介绍,所以本文着重介绍嵌套模版的使用。

虽然本文名称为嵌套模版的最佳实践,但是准确的讲,这只是最佳实践之一。如果读者有其它的实践方案,或者更好的处理模版嵌套的方案,欢迎讨论。

在我们开发web应用程序的时候,不可避免的要使用到模版。

一般一个网站包含很多的页面,比如新闻页面、注册页面、文章列表等。 不同的新闻可能使用同一个新闻布局模版,不同的文章详细页也可能使用同一个文章布局页面, 同时新闻布局模版和文章布局页面也可能有一些公用的东西,比如header、footer、导航栏等。如何将这些公用的东西抽取成统一的模版呢?

本文将逐步介绍这些技术, 首先介绍嵌套文件的使用。

Parse vs ParseFiles vs ParseBlob

首先我们看一下这三个文件有何不同。 事实上是五个文件:

funcParseFiles(filenames ...string) (*Template, error)

funcParseGlob(patternstring) (*Template, error)

func(t *Template) Parse(textstring) (*Template, error)

func(t *Template) ParseFiles(filenames ...string) (*Template, error)

func(t *Template) ParseGlob(patternstring) (*Template, error)

Parse用来解析一个字符串,字符串代表模版的内容,并且嵌套的模版也会和这个模版进行关联。

tmpl, err := template.New("name").Parse(...)

// Error checking elided

err = tmpl.Execute(out, data)

import"html/template"

...

t, err := template.New("foo").Parse(`\{\{define "T"\}\}Hello, \{\{.\}\}!\{\{end\}\}`)

err = t.ExecuteTemplate(out, "T","")

ParseFiles用来解析一组命名的文件模版,当模版定义在不同的文件中的时候,使用这个方法可以产生一个可执行的模版,模版执行的时候不会出错。

ParseGlob与ParseFiles类似,它使用filepath.Glob模式匹配的方式遍历文件,将这些文件生成模版。

这两个函数还可以作为*Template的方法使用。作为函数使用的时候,它返回模版的名字是第一个文件的名字,模版以第一个文件作为base模版。

同时后面的文件也会生成模版作为这个模版的关联模板,你可以通过Lookup方法查找到这个模版,因为每个模版都保存着它的关联模版:

set map[string]*Template

我们以一个例子演示一下嵌套模版的使用。

当前文件夹下有两个文件。

header.html

Title is \{\{.Title\}\}

\{\{template "footer"\}\}

footer.html

\{\{define "footer"\}\}Body is \{\{.Body\}\}\{\{end\}\}

测试程序:

packagemain

import(

"fmt"

"html/template"

"net/http"

)

funchandler(w http.ResponseWriter, r *http.Request) {

t, _ := template.ParseFiles("header.html","footer.html")

err := t.Execute(w, map[string]string{"Title":"My title","Body":"Hi this is my body"})

iferr !=nil{

panic(err)

}

}

funcmain() {

http.HandleFunc("/", handler)

http.ListenAndServe(":8080",nil)

}

浏览器访问http://localhost:8080/会得到渲染的结果:

Title is My title

Body is

可以看到结果基本符合预期。header.html嵌套了footer模版,渲染的时候以header.html为主模版显示,嵌套渲染了footer.html。

但是上面的结果显示有一点点问题,就是footer渲染的时候并没有显示body的结果,这是因为data传给了主模版,嵌套模版如果要使用这个数据,需要在嵌套的地方把data传递给它。我们可以修改header.html:

Title is \{\{.Title\}\}

\{\{template "footer"

这样footer.html就可以使用传入的data渲染了:

Title isMy title

Body isHithisismybody

在使用ParseFiles、ParseGlob函数的时候,默认以文件的路径的最后一个部分作为模版名称,

比如文件a/foo的模版名称为foo,但是如果参数中不同的文件夹下有相同的文件名时,最后那个同名的模版文件会"覆盖"前面的重名文件模版,官方库的实现中不能保存重名的模版文件。

Execute vs ExecuteTemplate

上面的例子显示了一个简单的嵌套模版的使用,但是如果我们把两个文件的顺序交换一下,如下所示:

funchandler(w http.ResponseWriter, r *http.Request) {

t, _ := template.ParseFiles("footer.html","header.html")

err := t.Execute(w, map[string]string{"Title":"My title","Body":"Hi this is my body"})

iferr !=nil{

panic(err)

}

}

运行后浏览器访问一下,会发现没报错,但是也没有渲染任何东西。

有疑问加站长微信联系(非本文作者)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值