模板引擎配置 #
一、模板引擎概述 #
Echo支持多种模板引擎,可以根据项目需求选择合适的引擎。
1.1 支持的模板引擎 #
| 引擎 | 说明 |
|---|---|
| Go Template | Go标准库模板 |
| Pongo2 | Django风格模板 |
| Jet | 高性能模板引擎 |
| Ace | 简洁的模板引擎 |
| Amber | Jade风格模板 |
| Handlebars | Handlebars模板 |
| Mustache | Mustache模板 |
1.2 模板引擎接口 #
go
type Renderer interface {
Render(w io.Writer, name string, data interface{}, c Context) error
}
二、Go标准模板 #
2.1 基本配置 #
go
package main
import (
"html/template"
"net/http"
"github.com/labstack/echo/v4"
)
type Template struct {
templates *template.Template
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
t := &Template{
templates: template.Must(template.ParseGlob("views/*.html")),
}
e.Renderer = t
e.GET("/", func(c echo.Context) error {
return c.Render(http.StatusOK, "index.html", map[string]interface{}{
"title": "首页",
"name": "张三",
})
})
e.Start(":8080")
}
2.2 模板文件 #
views/index.html
html
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<h1>Hello, {{.name}}!</h1>
</body>
</html>
2.3 模板目录结构 #
text
views/
├── layouts/
│ └── base.html
├── partials/
│ ├── header.html
│ └── footer.html
├── pages/
│ ├── index.html
│ └── about.html
└── errors/
├── 404.html
└── 500.html
2.4 模板继承 #
go
func main() {
e := echo.New()
t := &Template{
templates: template.Must(template.ParseFiles(
"views/layouts/base.html",
"views/pages/index.html",
"views/pages/about.html",
)),
}
e.Renderer = t
e.GET("/", func(c echo.Context) error {
return c.Render(http.StatusOK, "base.html", map[string]interface{}{
"title": "首页",
"content": "index.html",
})
})
e.Start(":8080")
}
views/layouts/base.html
html
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
{{template "content" .}}
</body>
</html>
{{define "content"}}
{{template .content .}}
{{end}}
2.5 模板函数 #
go
func main() {
e := echo.New()
funcMap := template.FuncMap{
"upper": strings.ToUpper,
"lower": strings.ToLower,
"title": strings.Title,
"safe": func(s string) template.HTML {
return template.HTML(s)
},
}
t := &Template{
templates: template.Must(template.New("").Funcs(funcMap).ParseGlob("views/*.html")),
}
e.Renderer = t
e.Start(":8080")
}
模板中使用:
html
<p>{{upper .name}}</p>
<p>{{lower .name}}</p>
<p>{{safe "<strong>Bold</strong>"}}</p>
三、Pongo2模板 #
3.1 安装 #
bash
go get github.com/flosch/pongo2/v6
3.2 配置Pongo2 #
go
package main
import (
"net/http"
"github.com/flosch/pongo2/v6"
"github.com/labstack/echo/v4"
)
type Pongo2Renderer struct {
templateSet *pongo2.TemplateSet
}
func (r *Pongo2Renderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
var ctx pongo2.Context
if data != nil {
ctx = data.(pongo2.Context)
}
tmpl, err := r.templateSet.FromFile(name)
if err != nil {
return err
}
return tmpl.ExecuteWriter(ctx, w)
}
func main() {
e := echo.New()
e.Renderer = &Pongo2Renderer{
templateSet: pongo2.NewFSLoader("views"),
}
e.GET("/", func(c echo.Context) error {
return c.Render(http.StatusOK, "index.html", pongo2.Context{
"title": "首页",
"name": "张三",
})
})
e.Start(":8080")
}
3.3 Pongo2模板语法 #
html
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
{% if user %}
<p>Welcome, {{ user.name }}!</p>
{% endif %}
{% for item in items %}
<li>{{ item.name }}</li>
{% endfor %}
{% include "partials/header.html" %}
{% extends "layouts/base.html" %}
{% block content %}
<p>Content here</p>
{% endblock %}
</body>
</html>
四、Jet模板引擎 #
4.1 安装 #
bash
go get github.com/CloudyKit/jet/v6
4.2 配置Jet #
go
package main
import (
"net/http"
"github.com/CloudyKit/jet/v6"
"github.com/labstack/echo/v4"
)
type JetRenderer struct {
set *jet.Set
}
func (r *JetRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
tmpl, err := r.set.GetTemplate(name)
if err != nil {
return err
}
vars := make(jet.VarMap)
return tmpl.Execute(w, vars, data)
}
func main() {
e := echo.New()
set := jet.NewSet(
jet.NewOSFileSystemLoader("./views"),
jet.InDevelopmentMode(),
)
e.Renderer = &JetRenderer{set: set}
e.GET("/", func(c echo.Context) error {
return c.Render(http.StatusOK, "index.jet", map[string]interface{}{
"title": "首页",
"name": "张三",
})
})
e.Start(":8080")
}
4.3 Jet模板语法 #
html
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello, {{ name }}!</h1>
{% if user %}
<p>Welcome, {{ user.name }}!</p>
{% endif %}
{% for item in items %}
<li>{{ item.name }}</li>
{% endfor %}
{% extends "layouts/base.jet" %}
{% block content %}
<p>Content here</p>
{% endblock %}
</body>
</html>
五、模板缓存 #
5.1 开发模式 #
go
func main() {
e := echo.New()
e.Debug = true
var t *Template
if e.Debug {
t = &Template{
templates: template.Must(template.ParseGlob("views/*.html")),
}
} else {
t = &Template{
templates: template.Must(template.ParseGlob("views/*.html")),
}
}
e.Renderer = t
e.Start(":8080")
}
5.2 热重载 #
go
type Template struct {
templates *template.Template
debug bool
files []string
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
if t.debug {
t.templates = template.Must(template.ParseFiles(t.files...))
}
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
files := []string{
"views/layouts/base.html",
"views/pages/index.html",
}
t := &Template{
templates: template.Must(template.ParseFiles(files...)),
debug: true,
files: files,
}
e.Renderer = t
e.Start(":8080")
}
六、错误处理 #
6.1 模板错误处理 #
go
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
err := t.templates.ExecuteTemplate(w, name, data)
if err != nil {
log.Printf("Template error: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, "模板渲染错误")
}
return nil
}
6.2 错误页面 #
go
e.HTTPErrorHandler = func(err error, c echo.Context) {
code := http.StatusInternalServerError
if he, ok := err.(*echo.HTTPError); ok {
code = he.Code
}
errorPage := fmt.Sprintf("errors/%d.html", code)
if err := c.Render(code, errorPage, map[string]interface{}{
"code": code,
"message": err.Error(),
}); err != nil {
c.String(code, err.Error())
}
}
七、完整示例 #
go
package main
import (
"html/template"
"io"
"net/http"
"strings"
"github.com/labstack/echo/v4"
)
type Template struct {
templates *template.Template
}
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return t.templates.ExecuteTemplate(w, name, data)
}
func main() {
e := echo.New()
funcMap := template.FuncMap{
"upper": strings.ToUpper,
"lower": strings.ToLower,
"title": strings.Title,
"safe": func(s string) template.HTML {
return template.HTML(s)
},
"add": func(a, b int) int {
return a + b
},
}
t := &Template{
templates: template.Must(template.New("").Funcs(funcMap).ParseGlob("views/*.html")),
}
e.Renderer = t
e.GET("/", home)
e.GET("/about", about)
e.GET("/users", users)
e.Logger.Fatal(e.Start(":8080"))
}
func home(c echo.Context) error {
return c.Render(http.StatusOK, "index.html", map[string]interface{}{
"title": "首页",
"message": "Welcome to Echo!",
})
}
func about(c echo.Context) error {
return c.Render(http.StatusOK, "about.html", map[string]interface{}{
"title": "关于我们",
"content": template.HTML(`
<p>这是一个Echo框架示例项目。</p>
<p>使用Go标准模板引擎。</p>
`),
})
}
func users(c echo.Context) error {
users := []map[string]string{
{"id": "1", "name": "张三", "email": "zhangsan@example.com"},
{"id": "2", "name": "李四", "email": "lisi@example.com"},
{"id": "3", "name": "王五", "email": "wangwu@example.com"},
}
return c.Render(http.StatusOK, "users.html", map[string]interface{}{
"title": "用户列表",
"users": users,
})
}
views/index.html
html
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<h1>{{.message}}</h1>
<p>Upper: {{upper .message}}</p>
<p>Lower: {{lower .message}}</p>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
<a href="/users">用户</a>
</nav>
</body>
</html>
views/about.html
html
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<h1>{{.title}}</h1>
{{.content}}
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
<a href="/users">用户</a>
</nav>
</body>
</html>
views/users.html
html
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
</head>
<body>
<h1>{{.title}}</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{{range .users}}
<tr>
<td>{{.id}}</td>
<td>{{.name}}</td>
<td>{{.email}}</td>
</tr>
{{end}}
</tbody>
</table>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
<a href="/users">用户</a>
</nav>
</body>
</html>
八、总结 #
模板引擎配置要点:
| 要点 | 说明 |
|---|---|
| Renderer接口 | 实现Render方法 |
| Go Template | 标准库模板 |
| Pongo2 | Django风格 |
| Jet | 高性能引擎 |
| 模板函数 | FuncMap注册 |
| 模板缓存 | 生产环境启用 |
准备好学习模板渲染了吗?让我们进入下一章!
最后更新:2026-03-28