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) {
  
Hello, { name }
} templ Greeting(person Person) {
@Hello(person.Name)
}

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