Gopongo2教程展示了如何使用pongo2template引擎在Golang中使用模板。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
模板引擎是一个库,旨在将模板与数据相结合以生成文档。模板引擎用于生成大量电子邮件、源代码预处理或生成动态HTML页面。
模板由静态数据和动态区域组成。动态区域后来被数据替换。渲染功能随后将模板与数据结合起来。模板引擎用于将模板与数据模型相结合以生成文档。
pongo2库是一个受Django模板引擎启发的Go模板引擎。
pongo2在模板字符串中使用各种分隔符:
{%%}-语句{{}}-打印到模板输出的表达式{##}-不包含在模板输出中的注释###-行语句
可以使用pongo2.FromString从字符串、使用pongo2.FromFile的文件或使用pongo2.FromBytes的字节读取模板。
文档使用Execute、ExecuteWriter或ExecuteBytes函数呈现。这些函数接受一个Context,它向模板提供常量、变量、实例或函数。
去pongo2.FromString
pongo2.FromString从字符串中读取模板。
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
func main() {
tpl, err := pongo2.FromString("Hello {{ name }}!")
if err != nil {
log.Fatal(err)
}
res, err := tpl.Execute(pongo2.Context{"name": "John Doe"})
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
该示例生成一条简单的文本消息。
tpl, err := pongo2.FromString("Hello {{ name }}!")
要打印的变量放在{{}}括号内。
res, err := tpl.Execute(pongo2.Context{"name": "John Doe"})
我们使用Execute呈现最终字符串。在上下文中,我们为name变量传递了一个值。
$ go run main.go Hello John Doe!
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
func main() {
tpl, err := pongo2.FromString("{{ name }} is a {{ occupation }}")
if err != nil {
log.Fatal(err)
}
name, occupation := "John Doe", "gardener"
ctx := pongo2.Context{"name": name, "occupation": occupation}
res, err := tpl.Execute(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
在这个例子中,我们在上下文中传递了两个变量。
$ go run main.go John Doe is a gardener
去pongo2.FromFile
使用pongo2.FromFile函数,我们从文件中读取模板。
{{ name }} is a {{ occupation }}
这是模板文件。
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
func main() {
tpl, err := pongo2.FromFile("message.tpl")
if err != nil {
log.Fatal(err)
}
name, occupation := "John Doe", "gardener"
ctx := pongo2.Context{"name": name, "occupation": occupation}
res, err := tpl.Execute(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
该示例在从文件读取模板时生成一条简单的消息。
去pongo2获取指令
for指令用于迭代模板中的数据集合。
{% for word in words -%}
{{ word }}
{% endfor %}
在模板中,我们使用for指令遍历words数据结构的元素。-字符去除空白字符。
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
func main() {
tpl, err := pongo2.FromFile("words.tpl")
if err != nil {
log.Fatal(err)
}
words := []string{"sky", "blue", "storm", "nice", "barrack", "stone"}
ctx := pongo2.Context{"words": words}
res, err := tpl.Execute(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
在程序中,我们将一段单词传递给模板引擎。我们得到一个单词列表作为输出。
$ go run main.go sky blue storm nice barrack stone
去pongo2过滤器
过滤器可以应用于数据以修改它们。在|之后应用过滤器性格。
{% for word in words -%}
{{ word }} has {{ word | length }} characters
{% endfor %}
length过滤器返回字符串的大小。
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
func main() {
tpl, err := pongo2.FromFile("words.tpl")
if err != nil {
log.Fatal(err)
}
words := []string{"sky", "blue", "storm", "nice", "barrack", "stone"}
ctx := pongo2.Context{"words": words}
res, err := tpl.Execute(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
在程序中,我们将一段单词传递给模板。我们打印每个单词及其大小。
$ go run main.go sky has 3 characters blue has 4 characters storm has 5 characters nice has 4 characters barrack has 7 characters stone has 5 characters
如果有条件就去pongo2
可以使用if/endif指令创建条件。
{% for todo in todos -%}
{% if todo.Done %}
{{- todo.Title -}}
{% endif %}
{% endfor %}
在模板文件中,我们使用if指令只输出完成的任务。
package main
import (
"fmt"
"log"
"github.com/flosch/pongo2/v5"
)
type Todo struct {
Title string
Done bool
}
type Data struct {
Todos []Todo
}
func main() {
tpl, err := pongo2.FromFile("todos.tpl")
if err != nil {
log.Fatal(err)
}
todos := []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
{Title: "Task 4", Done: false},
{Title: "Task 5", Done: true},
}
ctx := pongo2.Context{"todos": todos}
res, err := tpl.Execute(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
我们从一片待办事项中生成输出。在输出中,我们只包含已完成的任务。
服务器示例
在下一个示例中,我们在服务器应用程序中使用模板。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Users</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Name</th>
<th>Occupation</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.Name }} </td>
<td>{{ user.Occupation }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
输出是一个HTML文件。用户显示在HTML表格中。
package main
import (
"net/http"
"github.com/flosch/pongo2/v5"
)
type User struct {
Name string
Occupation string
}
var tpl = pongo2.Must(pongo2.FromFile("users.html"))
func usersHandler(w http.ResponseWriter, r *http.Request) {
users := []User{
{Name: "John Doe", Occupation: "gardener"},
{Name: "Roger Roe", Occupation: "driver"},
{Name: "Peter Smith", Occupation: "teacher"},
}
err := tpl.ExecuteWriter(pongo2.Context{"users": users}, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.HandleFunc("/users", usersHandler)
http.ListenAndServe(":8080", nil)
}
Web服务器返回一个HTML页面,其中包含/usersURL路径的用户表。
var tpl = pongo2.Must(pongo2.FromFile("index.html"))
pongo2.Must是一个辅助函数,它在应用程序启动时预编译模板。
err := tpl.ExecuteWriter(pongo2.Context{"users": users}, w)
ExecuteWriter使用给定的上下文呈现模板,并在成功时将输出写入响应编写器。没有写错;而是返回错误。
在本教程中,我们使用第三方pongo2模板引擎创建了动态文档。
列出所有Go教程。
