quicktemplate

quicktemplate介绍

Go的快速,强大且易于使用的模板引擎。 针对热路径中的速度,零内存分配进行了优化。比html/template快20倍,灵感来自Mako templates

  • 非常快。 模板转换为Go代码然后编译
  • Quicktemplate语法非常接近Go - 在开始使用quicktemplate之前无需学习另一种模板语言
  • 在模板编译期间几乎所有错误都被捕获,因此生产受模板相关错误的影响较小
  • 使用方便。有关详细信息,请参阅快速入门和示例
  • 强大。任意Go代码可以嵌入到模板中并与模板混合。小心这个功能 - 不要从模板中查询数据库and/or外部资源,除非你错过Go中的PHP方式:)这种功能主要用于任意数据转换
  • 易于使用的模板继承由Go接口提供支持。 请参阅此示例以获取详细信
  • 模板被编译为单个二进制文件,因此无需将模板文件复制到服务器

模板无法在服务器上动态更新,因为它们被编译为单个二进制文件。如果您需要快速模板引擎来简单动态更新模板,请查看fasttemplate

quicktemplate使用

首先,安装quicktemplate包和quicktemplate compiler

  1. go get -u github.com/valyala/quicktemplate
  2. go get -u github.com/valyala/quicktemplate/qtc

可以在https://github.com/valyala/quicktemplate找到完整的文档。

将模板文件保存到扩展名*.qtpl下的templates文件夹中,打开终端并在此文件夹中运行qtc

如果一切顺利,.qtpl.go文件必须出现在templates文件夹中。 这些文件包含所有 .qtpl文件的Go代码。

请记住,每次更改/templates/*.qtpl文件时,都必须运行qtc命令并重新构建应用程序。

目录结构

主目录herotemplate

  1. —— controllers
  2. —— execute_template.go
  3. —— hello.go
  4. —— index.go
  5. —— template
  6. —— base.qtpl
  7. —— hello.qtpl
  8. —— index.qtpl
  9. —— main.go
  10. —— main_test.go

代码示例

/controllers/execute_template.go

  1. package controllers
  2. import (
  3. "../templates"
  4. "github.com/kataras/iris"
  5. )
  6. // ExecuteTemplate将“tmpl”部分模板渲染给`context#ResponseWriter`。
  7. func ExecuteTemplate(ctx iris.Context, tmpl templates.Partial) {
  8. ctx.Gzip(true)
  9. ctx.ContentType("text/html")
  10. templates.WriteTemplate(ctx.ResponseWriter(), tmpl)
  11. }

文件名 /controllers/hello.go

  1. package controllers
  2. import (
  3. "../templates"
  4. "github.com/kataras/iris"
  5. )
  6. // Hello使用已编译的../templates/hello.qtpl.go文件渲染我们的../templates/hello.qtpl文件。
  7. func Hello(ctx iris.Context) {
  8. // vars := make(map[string]interface{})
  9. // vars["message"] = "Hello World!"
  10. // vars["name"] = ctx.Params().Get("name")
  11. // [...]
  12. // &templates.Hello{ Vars: vars }
  13. // [...]
  14. //但是,作为替代方案,我们建议您使用`ctx.ViewData(key,value)`
  15. //为了能够从中间件(其他处理程序)修改`templates.Hello #Vars`
  16. ctx.ViewData("message", "Hello World!")
  17. ctx.ViewData("name", ctx.Params().Get("name"))
  18. // set view data to the `Vars` template's field
  19. tmpl := &templates.Hello{
  20. Vars: ctx.GetViewData(),
  21. }
  22. //渲染模板
  23. ExecuteTemplate(ctx, tmpl)
  24. }

文件名 /controllers/index.go

  1. package controllers
  2. import (
  3. "../templates"
  4. "github.com/kataras/iris"
  5. )
  6. //索引使用已编译的../templates/index.qtpl.go文件渲染我们的../templates/index.qtpl文件。
  7. func Index(ctx iris.Context) {
  8. tmpl := &templates.Index{}
  9. //渲染模板
  10. ExecuteTemplate(ctx, tmpl)
  11. }

/templates/base.qtpl

  1. 这是我们模板的基础实现
  2. {% interface
  3. Partial {
  4. Body()
  5. }
  6. %}
  7. 模板编写实现Partial接口的模板
  8. {% func Template(p Partial) %}
  9. <html>
  10. <head>
  11. <title>Quicktemplate integration with Iris</title>
  12. </head>
  13. <body>
  14. <div>
  15. Header contents here...
  16. </div>
  17. <div style="margin:10px;">
  18. {%= p.Body() %}
  19. </div>
  20. </body>
  21. <footer>
  22. Footer contents here...
  23. </footer>
  24. </html>
  25. {% endfunc %}
  26. 基本模板实现。 如果需要,其他页面可以继承
  27. 仅覆盖某些部分方法。
  28. {% code type Base struct {} %}
  29. {% func (b *Base) Body() %}This is the base body{% endfunc %}

文件名 hello.qtpl

  1. Hello模板,实现了Partial的方法
  2. {% code
  3. type Hello struct {
  4. Vars map[string]interface{}
  5. }
  6. %}
  7. {% func (h *Hello) Body() %}
  8. <h1>{%v h.Vars["message"] %}</h1>
  9. <div>
  10. Hello <b>{%v h.Vars["name"] %}!</b>
  11. </div>
  12. {% endfunc %}

/templates/index.qtpl

  1. Hello模板,实现了Partial的方法。
  2. {% code
  3. type Index struct {}
  4. %}
  5. {% func (i *Index) Body() %}
  6. <h1>Index Page</h1>
  7. <div>
  8. This is our index page's body.
  9. </div>
  10. {% endfunc %}

main.go

  1. package main
  2. import (
  3. "./controllers"
  4. "github.com/kataras/iris"
  5. )
  6. func newApp() *iris.Application {
  7. app := iris.New()
  8. app.Get("/", controllers.Index)
  9. app.Get("/{name}", controllers.Hello)
  10. return app
  11. }
  12. func main() {
  13. app := newApp()
  14. // http://localhost:8080
  15. // http://localhost:8080/yourname
  16. app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
  17. }

main_test.go

  1. package main
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/kataras/iris/httptest"
  6. )
  7. func TestResponseWriterQuicktemplate(t *testing.T) {
  8. baseRawBody := `
  9. <html>
  10. <head>
  11. <title>Quicktemplate integration with Iris</title>
  12. </head>
  13. <body>
  14. <div>
  15. Header contents here...
  16. </div>
  17. <div style="margin:10px;">
  18. <h1>%s</h1>
  19. <div>
  20. %s
  21. </div>
  22. </div>
  23. </body>
  24. <footer>
  25. Footer contents here...
  26. </footer>
  27. </html>
  28. `
  29. expectedIndexRawBody := fmt.Sprintf(baseRawBody, "Index Page", "This is our index page's body.")
  30. name := "yourname"
  31. expectedHelloRawBody := fmt.Sprintf(baseRawBody, "Hello World!", "Hello <b>"+name+"!</b>")
  32. app := newApp()
  33. e := httptest.New(t, app)
  34. e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal(expectedIndexRawBody)
  35. e.GET("/" + name).Expect().Status(httptest.StatusOK).Body().Equal(expectedHelloRawBody)
  36. }