pongo2 is a Django-syntax compatible template engine for Go. This guide will help you get up and running quickly.
go get -u github.com/flosch/pongo2/v7package main
import (
"fmt"
"github.com/flosch/pongo2/v7"
)
func main() {
// Compile the template
tpl, err := pongo2.FromString("Hello {{ name|capfirst }}!")
if err != nil {
panic(err)
}
// Execute with context
out, err := tpl.Execute(pongo2.Context{"name": "florian"})
if err != nil {
panic(err)
}
fmt.Println(out) // Output: Hello Florian!
}package main
import (
"github.com/flosch/pongo2/v7"
"net/http"
)
// Pre-compile templates at startup for better performance
var tplExample = pongo2.Must(pongo2.FromFile("templates/example.html"))
func examplePage(w http.ResponseWriter, r *http.Request) {
err := tplExample.ExecuteWriter(pongo2.Context{
"query": r.FormValue("query"),
}, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.HandleFunc("/", examplePage)
http.ListenAndServe(":8080", nil)
}A Context is a map that provides variables to your template:
ctx := pongo2.Context{
"name": "John",
"age": 30,
"is_admin": true,
"items": []string{"apple", "banana", "cherry"},
"user": struct {
Name string
Email string
}{"John Doe", "[email protected]"},
}
out, err := tpl.Execute(ctx)In your template, access these values:
Hello {{ name }}!
You are {{ age }} years old.
{% if is_admin %}You are an admin.{% endif %}
Items:
{% for item in items %}
- {{ item }}
{% endfor %}
User: {{ user.Name }} ({{ user.Email }})Variables are enclosed in double curly braces:
{{ variable }}
{{ user.name }}
{{ items.0 }}
{{ dict.key }}Filters transform variable output:
{{ name|upper }}
{{ text|truncatewords:30 }}
{{ price|floatformat:2 }}
{{ items|join:", " }}Tags provide logic and control flow:
{% if condition %}...{% endif %}
{% for item in items %}...{% endfor %}
{% include "header.html" %}
{% extends "base.html" %}{# This is a comment #}
{% comment %}
This is a
multi-line comment
{% endcomment %}For production, use FromCache to avoid recompiling templates on every request:
tpl, err := pongo2.FromCache("templates/page.html")In debug mode, set Debug to true to disable caching:
pongo2.DefaultSet.Debug = truepongo2 provides several ways to execute templates:
// Returns rendered template as string
out, err := tpl.Execute(ctx)
// Returns rendered template as []byte
bytes, err := tpl.ExecuteBytes(ctx)
// Writes to an io.Writer (buffered, safe on error)
err := tpl.ExecuteWriter(ctx, w)
// Writes to an io.Writer (unbuffered, faster but partial output on error)
err := tpl.ExecuteWriterUnbuffered(ctx, w)
// Execute specific blocks only
blocks, err := tpl.ExecuteBlocks(ctx, []string{"content", "sidebar"})Set variables available to all templates in a set:
pongo2.Globals["site_name"] = "My Website"
pongo2.Globals["current_year"] = time.Now().Year()
// Or use a custom TemplateSet
mySet := pongo2.NewSet("custom", pongo2.DefaultLoader)
mySet.Globals["api_url"] = "https://api.example.com"By default, pongo2 automatically escapes HTML in variable output. Control this behavior:
// Disable globally
pongo2.SetAutoescape(false)
// Or in templates
{% autoescape off %}
{{ raw_html }}
{% endautoescape %}
// Or mark individual values as safe
{{ html_content|safe }}pongo2 provides detailed error information:
tpl, err := pongo2.FromString("{{ invalid syntax }}")
if err != nil {
// err contains file, line, column information
fmt.Printf("Template error: %v\n", err)
}- Template Syntax - Complete syntax reference
- Filters - All available filters
- Tags - All available tags
- Template Sets - Advanced configuration
- Custom Extensions - Create your own filters and tags