Golang 有很多的模版引擎,自带的 html/template
也很好,大多数情况都能满足需求,只是有些逻辑、条件判断不好在模版里实现, quicktemplate
是个很好的选择。
golang 一些预编译模版的性能比较
再看看模版的语法解析,综合性能与语法, quicktemplate
是个非常好的选择。
quicktemplate 入门
下面简单介绍一下 quicktemplate 模版的使用方法,将定义两个页面:首页、用户列表页
新建一个 base.qtpl
文件作为基本页面或叫 layout
,规定以 qtpl
为后缀名。
定义 Page
interface
1
2
3
4
5
6
{% interface
Page {
Title()
Body()
}
%}
和 PageTemplate
函数,以 Page
为参数
1
2
3
4
5
6
7
8
9
10
{% func PageTemplate(p Page) %}
<html>
<head>
<title>{%= p.Title() %}</title>
</head>
<body>
{%= p.Body() %}
</body>
</html>
{% endfunc %}
定义首页
定义 BasePage
struct
1
2
3
4
{% code type BasePage struct {
HeadTitle string
MainBody string
} %}
给 BasePage 定义 Title()
和 Body()
函数/方法
1
2
3
4
5
6
7
8
9
{% func (p *BasePage) Title() %}{%s p.HeadTitle %}{% endfunc %}
{% func (p *BasePage) Body() %}
<div>
<a href="/users">goto users page</a>
</div>
<h1>{%s p.HeadTitle %}</h1>
<p>{%s p.MainBody %}</p>
{% endfunc %}
这样首页模版就定义好了,首页的 handler
调用:
1
2
3
4
5
6
7
8
func Home(w http.ResponseWriter, r *http.Request) {
p := &templates.BasePage{
HeadTitle: "Home page",
MainBody: "This is a home body",
}
templates.WritePageTemplate(w, p)
}
定义用户列表页
新建 users.qtpl
文件
用户列表页可以继承 BasePage struct
1
2
3
4
{% code type UsersPage struct {
BasePage
Users []string
} %}
这里我只需重新定义 Body()
方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% func (p *UsersPage) Body() %}
<div>
<a href="/">return to main page</a>
</div>
<h1>{%s p.HeadTitle %}</h1>
<p>{%s p.MainBody %}</p>
{% if len(p.Users) > 0 %}
<ul>
{% for i, name := range p.Users %}
<li> {%d i %} - {%s name %}
{% endfor %}
</ul>
{% endif %}
{% endfunc %}
当然也可以覆盖 Title()
方法,如:
1
{% func (p *BasePage) Title() %}{%s p.HeadTitle %} - balabala {% endfunc %}
对应的 handler
1
2
3
4
5
6
7
8
9
10
11
12
func Users(w http.ResponseWriter, r *http.Request) {
p := &templates.UsersPage{
BasePage: templates.BasePage{
HeadTitle: "Users page",
MainBody: "This is a Users page body",
},
Users: []string{
"Google", "Baidu", "Bing", "Sogo",
},
}
templates.WritePageTemplate(w, p)
}
当模版有修改后必须在网站根目录(main.go目录)实行命令 qtc templates
,templates 是模版文件存放的目录
完整代码
文件结构
1
2
3
4
5
6
7
8
├── go.mod
├── go.sum
├── main.go
└── templates
├── base.qtpl
├── base.qtpl.go
├── users.qtpl
└── users.qtpl.go
其中 *.qtpl.go
文件是实行命令 qtc templates
后自动生成的 go
文件,里面有相应的方法可以 handler
里调用。
以下是完整文件内容
main.go 文件
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
31
32
33
34
package main
import (
"net/http"
"qktp/templates"
)
func main() {
http.HandleFunc("/users", Users)
http.HandleFunc("/", Home)
_ = http.ListenAndServe(":8080", nil)
}
func Home(w http.ResponseWriter, r *http.Request) {
p := &templates.BasePage{
HeadTitle: "Home page",
MainBody: "This is a home body",
}
templates.WritePageTemplate(w, p)
}
func Users(w http.ResponseWriter, r *http.Request) {
p := &templates.UsersPage{
BasePage: templates.BasePage{
HeadTitle: "Users page",
MainBody: "This is a Users page body",
},
Users: []string{
"Google", "Baidu", "Bing", "Sogo",
},
}
templates.WritePageTemplate(w, p)
}
templates/base.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
31
32
33
34
{% interface
Page {
Title()
Body()
}
%}
{% func PageTemplate(p Page) %}
<html>
<head>
<title>{%= p.Title() %}</title>
</head>
<body>
{%= p.Body() %}
</body>
</html>
{% endfunc %}
{% code type BasePage struct {
HeadTitle string
MainBody string
} %}
{% func (p *BasePage) Title() %}{%s p.HeadTitle %}{% endfunc %}
{% func (p *BasePage) Body() %}
<div>
<a href="/users">goto users page</a>
</div>
<h1>{%s p.HeadTitle %}</h1>
<p>{%s p.MainBody %}</p>
{% endfunc %}
templates/users.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
{% code type UsersPage struct {
BasePage
Users []string
} %}
{% func (p *UsersPage) Body() %}
<div>
<a href="/">return to main page</a>
</div>
<h1>{%s p.HeadTitle %}</h1>
<p>{%s p.MainBody %}</p>
{% if len(p.Users) > 0 %}
<ul>
{% for i, name := range p.Users %}
<li> {%d i %} - {%s name %}
{% endfor %}
</ul>
{% endif %}
{% endfunc %}
参考
- golang 模版引擎性能比较 https://github.com/SlinSo/goTemplateBenchmark
- 比 html/template 快20倍的模版引擎 https://github.com/valyala/quicktemplate
使用 gin
只需修改 main.go 文件
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
31
32
33
34
35
36
package main
import (
"github.com/gin-gonic/gin"
"qktp/templates"
)
func main() {
router := gin.Default()
router.GET("/users", Users)
router.GET("/", Home)
_ = router.Run(":8082")
}
func Home(c *gin.Context) {
p := &templates.BasePage{
HeadTitle: "Home page",
MainBody: "This is a home body",
}
templates.WritePageTemplate(c.Writer, p)
}
func Users(c *gin.Context) {
p := &templates.UsersPage{
BasePage: templates.BasePage{
HeadTitle: "Users page",
MainBody: "This is a Users page body",
},
Users: []string{
"Google", "Baidu", "Bing", "Sogo",
},
}
templates.WritePageTemplate(c.Writer, p)
}
本文网址: https://golangnote.com/topic/288.html 转摘请注明来源