dcreager.net

Generating HTML from Go

A variety of techniques for generating HTML content from Go.

Templating

The canonical approach is to use templates, primarily the html/template stdlib package. The “Let's Go” book leans heavily on this approach.

html/template [Go]

“Let's Go” Web development ebook

There are other templating languages that you can use, too. There are dozens of implementations of Mustache templating, and at least one robust implementation of Jinja templates. (Though this is much less popular — if you're going for the templating route, html/template is by far the most paved path.)

Mustache templates

Go packages called mustache

Jinja templates

nikolalohinski/gonja [Go]

For all of these approaches, the templates are stored out-of-band in separate files. (Though note recent best practice has been to embed those files into your executable using go:embed, so that the individual template files don't need to be distributed separately.)

go:embed

JSX-style

Another popular choice is templ, which implements JSX-style templating.

templ

Here, the templates are not stored in separate files, but are inlined directly into your Go code. That requires a syntax extension, with (e.g.) HTML elements appearing directly in the source code:

templ Hello(name string) {
  <div>Hello, { name }</div>
}

templ Greeting(person Person) {
  <div class="greeting">
    @Hello(person.Name)
  </div>
}

A go:generate preprocessor translates this into a Go file, which is then compiled along with the rest of your code. In the case of templ, each template is translated into a Go function (or method) that returns a Component, which is just something that knows how to render itself into an io.Writer.

Fluent APIs

The benefit of the JSX-style approach is that the HTML portions of your templates continue to look like actual HTML. The main drawback is that your templ files aren't (pure) Go files, so existing tooling doesn't work on them.

Fluent APIs decide to resolve that trade-off in the other direction, by providing pure Go libraries that you call from regular Go code. The gomponents equivalent of the above example is:

import . "maragu.dev/gomponents"
import . "maragu.dev/gomponents/html"

func Hello(name string) Node {
    return Div(Text("Hello, " + name))
}

func Greeting(person Person) Node {
    return Div(
        Class("greeting"),
        Hello(person.Name),
    )
}

Note that this is largely the same API shape as templ. (The Component and Node interfaces are basically identical — something that “knows how to render itself into an io.Writer.) But instead of translating a JSX-like syntax into this function, you just write it directly.

There are several takes on this idea:

gomponents

delaneyj/gostar

rohanthewiz/element

» Languages » Go

» Web stuff