Golang from Python

Go HTML Templates: Not Jinja2

My first impression of Go's template system was pretty rough — and to understand why, let's talk about Jinja2. To make a page in Python, I inherit most of the structure from a base template:

{# base.html #}
<html>
<head><title>{% block title %}OVERRIDE THIS{% endblock %}</title></head>
<body>

{% block content %}{% endblock %}
</body></html>

If I wanted to write an index.html, I'd start from base.html and override the sections marked with {% block %} and {% endblock %} tags:

{# index.html #}
{% extends "base.html" %}

{% block title %}Index{% endblock %}

{% block content %}
This is the index page!
{% endblock %}

When you render a template that extends another, it takes the base content and fills in any blocks overridden in the children. So, rendering index.html would look like:

<html>
<head><title>Index</title></head>
<body>

This is the index page!
</body></html>

Go's template system is not like that.

It took me back to my time with PHP — which is the last thing I ever expected to say about Go. To render a page with common scaffolding in html/template, you break base.html up into a header and footer, and include them at the top and bottom:

header.html:

<html>
<head><title>{{ . }}</title></head>
<body>

footer.html:

</body></html>

index.html:

{{ template "header.html" "Index" }}

This is the index page!

{{ template "footer.html" }}

This felt like a step back: Jinja2's blocks took time to learn, but they let you build HTML content in a way that made total sense — write elements, and slot them into place. Go's template system is less abstract — to add a common header, you put a {{ template "header.html" }} exactly where you want it to show up.

While I miss Jinja2's abstractions, I've also started to appreciate the directness of Go's templates. In the next post, I talk a bit about how Go applies templates to values — it's also very different from Jinja2, and (like many things in the Go standard library) as you get into the details, Go's choices start making more sense.