在 quicktemplate 刚开源时就关注,只是当时觉得太麻烦了,没有去尝试,现在刚好有兴趣试试,发现不但没那么难,而且还很方便,顺便记一点快速入门及实践经验。
语法
这个 blog 程序模版用 quicktemplate 实现下来用得最多的就下面几个标签:
{% if true %} abc {% endif %}
{% for k, v := range slice %} {%d k %} {%s v %} {% endfor %}
- 字符类型
{%s str %}
、{%s= str %}
- 数字类型
{%d number %}
数字类型多一点,习惯了也不难
1
2
3
{%d int %} and {%dl int64 %} {%dul uint64 %} for integers.
{%f float %} for float64. Floating point precision may be set
via {%f.precision float %}. For example, {%f.2 1.2345 %} outputs 1.23.
实践
模版文件 qtpl
存放在 model
文件夹,因为要在 handle 要调用 modle ,模版文件里的脚本可以直接使用同个文件夹里定义的 struct
,不需要另外导入,避免相互导入。
文件结构
新建一个 qtpl
文件,如 base_page.qtpl
首先要定义一个 interface
,如:
1
2
3
4
5
6
7
8
{% interface
Page {
Header()
Body()
Aside()
Footer()
}
%}
再写一个函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% func PageTemplate(p Page) %}
<html>
<head>
{%= p.Header() %}
</head>
<body>
<article>
{%= p.Body() %}
</article>
<aside>
{%= p.Aside() %}
</aside>
<footer>
{%= p.Footer() %}
</footer>
</body>
</html>
{% endfunc %}
这个是定义一个 layout
页面,没有变量的内容块都可以写在里面,比如 header 里面的静态内容等可以添加进去:
1
2
3
4
5
6
<head>
<meta charset="utf-8">
<meta content="True" name="HandheldFriendly" />
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
{%= p.Header() %}
</head>
这个函数是在 handle 里调用 model.WritePageTemplate(ctx, p)
接下来定义基本页 basePage struct
包含所有页面的用到的属性,如:
1
2
3
4
5
6
BasePage struct {
Title string
Keywords string
Description string
Canonical string
}
紧接着定义 BasePage 的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% func (p *BasePage) Header() %}
<title>{%s p.Title %}</title>
<meta name="description" content="{%s p.Description %}">
<meta name="keywords" content="{%s p.Keywords %}">
<link rel="canonical" href="{%s p.Canonical %}">
{% endfunc %}
{% func (p *BasePage) Body() %}
This is a base body
{% endfunc %}
{% func (p *BasePage) Aside() %}
This is a base aside
{% endfunc %}
{% func (p *BasePage) Footer() %}
This is a base Footer
{% endfunc %}
内容可以随便写,也可以写具体的,如何选择,看个人情况。原则是 BasePage struct
里面有的数据都尽量满上,比如说一个网站的页头Header、边栏Aside、页脚Footer都相同,只有主体Body不同,那应该把Header、Aside、Footer 的内容都填写完整,并且 BasePage struct
里面应该包含 Header、Aside、Footer
所需要的所有属性、变量,这样可以避免多次重复的定义。
上面的内容都可以放在 base_page.qtpl
文件里。
以后所有的页面都继承这个 struct,只需添加对应的属性。以首页为例:
建立一个 home_page.qtpl
文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 这外面的文字随便写,可以当注释,不会参与编译,行头可以不用加斜杠,这里加只为代码高亮显示美观
// 定义一个 HomePage 继承 BasePage,同时添加首页列表需要的 NewsList (这只是举例)
{% code
type HomePage struct {
BasePage
NewsList []NewsStruct
}
%}
// 然后写一个方法覆盖 Body 内容
{% func (p *HomePage) Body() %}
<ul>
{% for _, item := range p.NewsList %}
<li><a href="/news/{%d item.ID %}">{%s item.Title %}</a></li>
{% endfor %}
</ul>
{% endfunc %}
// 如果想改变边栏Aside 内容就写
{% func (p *HomePage) Aside() %}
这是首页的侧栏内容。
{% endfunc %}
在 handle 里调用
1
2
3
4
5
p := &model.HomePage{}
model.WritePageTemplate(ctx, p)
ctx.SetContentType("text/html; charset=utf-8") // 这行也很关键,否则默认下载文件
主体搞定,其它页照葫芦画瓢
当有页面改动时都需要在 modle 文件夹下敲一个命令 qtc
,然后运行程序看看,只要编译过就可以稳定运行。
总结
模版的渲染速度相对数据的读取来说所用时间可以忽略不计,如果不对性能有很高要求,选择适合自己习惯就好,个人觉得 quicktemplate 入门较难,很不适应,一旦入门后会很喜欢这种写模版的方式。
感谢 quicktemplate 项目 https://github.com/valyala/quicktemplate