Golang from Python

Go HTML Templates: Functions and Flow

Here's a Jinja2 template I ported to Go:

{% for user in users %}
<input type="checkbox"
       name="users"
       value="{{ user.guid }}"
       id="user-{{ user.guid }}"
       {% if user.guid in selected_users %} checked{% endif %}>
<label for="user-{{ user.guid }}">{{ user.name }}</label>
{% endfor %}

It renders a checkbox list of users, some of whom are pre-selected. I'm going to focus on the test {% if user.guid in selected_users %}. In Python, I passed a list of guids, and was done. There's no generic Go function for "slice contains," so I tried some silly things - first, I tried to register a template function.

Actually registering the function was easy: call Template.Funcs before parsing your templates, with a mapping of strings to your new functions. I gave up on this approach because the most generic contains function I could write would only work on []string containers. Since I couldn't make something globally useful, I tried passing a contains function to the template itself:

var ctx struct{
    Users []db.User
    Selected func(string)bool
}
ctx.Users, err = listUsers() // error handling left to the imagination
ctx.Selected = func(guid string) {
    for _, u := range selectedUsers {
        if u == guid {
            return true
        }
    }

    return false
}

templates.ExecuteTemplate(w, "form.html", ctx)

This had more promise — calling the function looked like this: {{ if index $.Selected .Guid }}. It worked, but ultimately, it was less clear than a map[string]bool, and more code. The test {{ if index .Map $key }} treats missing keys as false, so you only need to fill in the true keys.

In the Go code above, you can see that I'm rendering templates by applying them to anonymous structs. It's concise if you only call the template once; for templates I have to reuse (mostly forms), unexported structs work well.