GoLang简便模板缓存实现
在GoLang开发中,当项目运行时,go的html/template默认行为是每次请求都得重新解析模板文件,当高并发,频繁的磁盘读取会造成非常大的负担,成为明显瓶颈,所以,为了避免重复解析模板文件,减少磁盘I/O和CPU开销,模板缓存系统诞生。
以下是非常简便的模板缓存系统的实现,大家可以根据这个简便的例子来理解这个系统。
文件准备
模板页面 base.page.html
{{define "base"}}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Document</title>
</head>
<body>
{{block "content" .}}
{{end}}
</body>
</html>
{{end}}
目标页面 home.page.html
{{template "base" .}}
{{define "content"}}
<div class="container">
<div class="row">
<div class="col">
<h1>This is the Home Page</h1>
<p>This is some text</p>
</div>
</div>
</div>
{{end}}
我们这里准备了一个模板页面和一个目标文件,可以看到目标文件是以模板文件来设计布局的。
然后我们可以开始设计模板缓存系统了。
首先,我们先make出一个map,key键值存目标页面的名字,value值存模板的相关信息
var tc = make(map[string]*template.Template)
然后,每次刷新页面后,我们先到这个map中查询是否存在这个名字的页面模板,如果不存在,我们需要从磁盘读取这个页面文件(第一次从磁盘中加载),并将这个模板存进这个map中,实现缓存的效果;如果读取到了,那就直接从缓存读取这个模板,页面被快速地刷新读取出来,比从磁盘读取的速度快很多。
func RenderTemplate(w http.ResponseWriter, t string) {
var tmpl *template.Template
var err error
_, inMap := tc[t]
if !inMap {
//需要将这个模板放进tc切片中
err = CreateTemplateCache(t)
if err != nil {
log.Println(err)
}
log.Println("模板未使用过,正在创建模板缓存...")
} else {
log.Println("正在使用模板缓存...")
}
tmpl = tc[t]
err = tmpl.Execute(w, nil)
}
接着,我们再创建一个创建模板缓存的函数,也就是将模板存入map中。
这段代码实现了一个模板缓存的创建函数,接收模板名称参数后,自动拼接该模板文件路径和基础布局模板路径,调用Go标准库的 template.ParseFiles 一次性解析这两个文件,将解析后的模板对象存入全局缓存映射 tc 中,若解析过程中遇到文件不存在或模板语法错误则立即返回错误,否则成功缓存供后续请求直接复用,避免了每次HTTP请求都重复读取磁盘和解析模板的开销。
func CreateTemplateCache(t string) error {
templates := []string{
fmt.Sprintf("./template/%s", t),
"./template/base.layout.html",
}
tmpl, err := template.ParseFiles(templates...)
if err != nil {
return err
}
tc[t] = tmpl
return nil
}
最后我们查看实现的效果,可以看到第一次是从磁盘读取的,后面刷新了几次,就从缓存中直接读取了。

到这里,一个非常简便的模板缓存系统就完成了。
更多推荐

所有评论(0)