simple template of golang,keeps all Templates in memory as map

写在前面

前些日子,在使用Golang写业务逻辑时,有一个功能需要渲染几个HTML的页面。使用了Golang原生的template模板库,虽然Golang的这个库口碑不是很好,不过需求也比较简单,因此就凑合着用了。就像这里给出的示例一样,把需要渲染的内容写到代码里,然后Parse,接着嵌入数据。

后来,随着新需求的不断提出,业务越来越复杂(这是大部分的系统的宿命:代码越来越多,越来越复杂),需要渲染的页面越来越多。发现事情不对啊,于是造了个轮子:Simplate

适应人群

入门——初级√——中级——高级;本文适应初级及以上。

我需要的Golang模板的样子

如果到Github上搜索,然而并没有发现自己需要的库。要么与一些框架强耦合,要么侧重定义一些新的语法,都不满足我的需求。我理想中的Golang库应该是这样的:

在意识到上面的问题后,我从几个现有的Web框架中寻找灵感,因为我维护的WhereSmile.com是基于beego开发的,了解beego具有模板管理的相应模块;同时了解到Ginecho这两个热度很高的Web框架没有模板相关模块,因此决定从beego项目中寻找灵感。

Simplate及其应用

在看了beego源码后,发现其模板部分具有很高的可塑性,于是把其模板相关的一部分代码抽离出来,即形成现在的库Simplate

Simplate会加载并解析特定目录下的所有模板文件,把每个文件解析成的Template对象保存在一个Map对象中,使用时传入特定的索引值(key值)即可。

快速使用指南

Simplate最大的优点是,可以在一个特定目录中统一管理所有的模板文件,同时以一种优雅的方式解决了模板嵌套的问题。

1)在项目目录下创建模板文件夹及模板文件

项目的整体目录结构可能类似于下面所示:

|-app (业务逻辑目录)
    |--home.go
    |--about.go
|-lib (其他逻辑目录)
|-views (模板目录)
    |--home (对应业务逻辑目录)
        |--index.html
        |--head.tpl
        |--body.tpl
    |--layout (存放布局模板文件)
        |--default.html
|-main.go

其中views目录包含了所有的模板文件(业务&布局)。需要说明的是:1)在业务模板中可以通过key值嵌套引入其他模板,比如在 home/index.html 中通过 {{ template "home/head.tpl" . }} 语句显式嵌入模板 home/head.tpl。2)布局模板中需要包含 {{ .LayoutContent }} 语句,当业务模板渲染完以后,被渲染的内容会赋值给LayoutContent这个变量传递给模板文件。

模板文件的可能样式如下:

<html>
  <head>
    <style type="text/css">
      body {background-color: red}
      p {margin-left: 20px}
    </style>
  </head>
  <body>
  
    {{ if .LayoutContent }}{{ .LayoutContent }} {{ end }}
  
  </body>
</html>

2) 初始化simplate并渲染模板

import "github.com/chalvern/simplate"

func InitIsmplate(){
  simplate.ViewsPath  = "your-templates-dir" // default is "views"
  simplate.LayoutFile = "your-layout-file" // default is "layout/default.html"

  // initial
  simplate.InitTemplate()
}

func YourCode() error {
  data := make(map[string]interface{})
  // data["Jingwei"] = "https://jingwei.link"
  // 这里把渲染的内容输出到标准输出
  return simplate.ExecuteTemplate(os.Stdout,"home/body.html", data)
}

func YourCodeTwo() error {
  data := make(map[string]interface{})
  // data["site"] = "https://WhereSmile.com"
  // 当有多个布局时,指定特定的布局,把渲染的内容输出到标准输出
  return simplate.ExecuteViewPathTemplateWithLayout(os.Stdout, "layout/default.html", "home/body.html", data)
}

3)更进一步的理解

按照第1步中的目录结构,views目录下的模板在被Simplate结构化后,会形成一个map[string]*template.Template的类型值。这个值在Simplate源码中的变量是simplateViewPathTemplates ,其中索引值(string类型的key值)是 []string{"home/body.tpl","home/head.tpl","home/index.html","layout/default.html"}

小结

Simplate库是从业务出发抽象出的一个公共库,轻量级的Golang模板管理库,非常适合在小应用中使用。比如对于那些需要发送邮件内容的小型应用,既不想引入大的框架(比如beego),又想很好地管理自己的邮件模板,此库就非常合适。

欢迎大家到Simplate帮忙点亮一颗Star,感谢!

参考