EvolveDev
Theme toggle is loading

Learn Go Templates: A Practical Guide to Layouts, Data Binding, and Rendering

Go templates provide a powerful way to generate dynamic content, whether for text-based output or rendering HTML pages. They are part of the standard library, making them efficient, secure, and easy to integrate into any Go application. With a simple yet flexible syntax, Go templates allow you to embed data, create reusable layouts, and structure content effectively. In this guide, we'll explore how to use templates, pass data, manage layouts, and solve common rendering challenges with practical examples.

Published: Mar 09, 2025

Learn Go Templates: A Practical Guide to Layouts, Data Binding, and Rendering

Introduction

Go templates provide a powerful way to generate dynamic content, whether for text-based output or rendering HTML pages. They are part of the standard library, making them efficient, secure, and easy to integrate into any Go application. With a simple yet flexible syntax, Go templates allow you to embed data, create reusable layouts, and structure content effectively. In this guide, we'll explore how to use templates, pass data, manage layouts, and solve common rendering challenges with practical examples.

Overview

In Go, there are two built-in packages for templating: text/template and html/template. The text/template package is used for generating plain text output, while html/template is specifically designed for rendering structured HTML. Both share the same syntax and features.

What You’ll Learn

Basics of Go Templates

A template in Go is a text file with placeholders that are replaced dynamically when rendered. These placeholders are written using {{ ... }} syntax.

Simple Example

// template
tmpl := "hey {{ .Word }}"
 
t, err := template.New("example").Parse(tmpl)
if err != nil {
    log.Fatal(err)
}
 
err = t.Execute(os.Stdout, map[string]any{Word: "there"})
if err != nil {
    log.Fatal(err)
}

This will print out "hey there" in your terminal. While this works, it's not an ideal scenario.
Keeping templates as separate files makes them easier to manage, reuse, and update without modifying the Go code.

Loading Templates from Filesystem

Create a file called example.tmpl inside templates, i.e. templates/example.tmpl.

contents of example.tmpl

hello {{ .Word }}

The placeholder "Word" will be replaced with whatever we pass in as data while executing this template.

// Make sure imports are correct.
import (
    "os"
    "log"
    "text/template"
)
 
tmpls := template.Must(template.ParseGlob("templates/*.tmpl"))
err := tmpls.ExecuteTemplate(os.Stdout, "example.tmpl", map[string]any{"Word": "world"})
if err != nil {
    log.Fatal(err)
}

The above code loads all the files with .tmpl extension, so that we can execute any template.

Working with HTML Templates

Go templates shine for those who want to build a website and render HTML pages easily.

Loading HTML Templates from Filesystem

The process is very similiar to the previous example with only changes being, the extension and import.

// Make sure imports are correct.
import (
    "os"
    "log"
    "html/template" // this changed
)
 
tmpls := template.Must(template.ParseGlob("templates/*.html")) // extension changed
err := tmpls.ExecuteTemplate(os.Stdout, "example.html", map[string]any{"Word": "world"})
if err != nil {
    log.Fatal(err)
}

Rendering a HTML Template in Browser

We'll be creating a simple http server to render a page with templates.

contents of home.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ .Title }}</title>
  </head>
  <body>
    Hey, There!
  </body>
</html>
func handleGetHome(w http.ResponseWriter, r *http.Request) {
    tmpls.ExecuteTemplate(w, "home.html", map[string]any{"Title":"Home Page"})
}
 
http.HandleFunc("/", handleGetHome)
http.ListenAndServe(":3000", nil)

Now, visit http://localhost:3000, you'll see the html being rendered.

Using Loops and Conditionals in Go Templates

Go templates support basic control structures like loops and conditionals, making it easy to handle dynamic content.

Looping with range

Use range to iterate over slices, maps, etc.

template:

<ul>
  {{ range .Items }}
  <li>{{ . }}</li>
  {{ else }}
  <li>No items found.</li>
  {{ end }}
</ul>

go code:

data := map[string]any{
	"Items": []string{"Go", "Python", "Rust"},
}
tmpls.ExecuteTemplate(w, "example.html", data)

Using Conditionals (if, else)

Example: Checking for a Value

{{ if .IsLoggedIn }}
<p>Welcome back, {{ .Username }}!</p>
{{ else }}
<p>Please log in.</p>
{{ end }}

Using Custom Functions in Go Templates

Go allows defining custom functions and passing them to templates using a FuncMap. This is useful for formatting data, modifying strings, or adding extra logic inside templates.

template:

<p>Original: {{ .Name }}</p>
<p>FirstName: {{ getFirstName .Name }}</p>

go code:

// Define custom functions
funcs := template.FuncMap{
	"getFirstName": func(name string) string {
		return strings.Split(name, " ")[0]
	},
}
tmpls := template.Must(template.New("").Funcs(funcs).ParseGlob("templates/*.html"))

Using Components in Go Templates

In Go templates, components (also called partials) help reuse smaller templates inside larger ones. This avoids code duplication and makes templates more modular.

Example: Reusing a Header Component

📂 Folder Structure

/templates
    ├── header.html
    ├── page.html

contents header.html

<header>
  <h1>{{ .Title }}</h1>
</header>

contents page.html

{{ template "header.html" }}
<p>Welcome to the page</p>

Using Layouts in Go Templates

When building web pages, we usually want to reuse a layout for multiple pages to reduce code duplication, but it's very hard to do so with templates.

How Layouts Work in Go

Unlike some templating engines that use {{ block }} and {{ define }}, we’ll use a custom function to inject a template inside a layout dynamically. This gives us more control and flexibility over rendering.

Defining Custom Function for Layouts

We’ll define a function (embed) that renders a given template inside a layout. This allows us to reuse a single layout file across multiple pages.

contents Layout.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ .Title }}</title>
  </head>
  <body>
    {{ embed .Page . }} <!-- Embed the page content here -->
  </body>
</html>

contents of Page.html

<h1>Welcome to {{ .Title }}</h1>
<p>This is a dynamic page using a layout.</p>

Registering embed function

tmpl := template.New("")
funcs := template.FuncMap{
	"embed": func(name string, data any) template.HTML {
		var out strings.Builder
		if err := tmpl.ExecuteTemplate(&out, name, data); err != nil {
			log.Println(err)
		}
 
		return template.HTML(out.String())
	},
}
 
tmpls := template.Must(tmpl.Funcs(funcs).ParseGlob("templates/*.html"))

Usage

func handler(w http.ResponseWriter, r *http.Request) {
  // This is the layout name which we're gonna use.
  tmpls.ExecuteTemplate(w, "Layout.html", map[string]any{
    "Page": "Page.html", // This is the page name
    "Title": "Example Page",
  })
}

Full Example here.

Resources

If you want to dive deeper into Go templates, here are some useful links:

If you're planning to use Go templates in a real web application, Gospur provides a more structured approach to working with them.

Conclusion

Go templates provide a simple yet powerful way to generate dynamic content, whether for rendering HTML pages in a web app or formatting text output. With features like loops, conditionals, custom functions, and layouts, they offer flexibility while keeping things lightweight. By structuring templates well and using functions like embed shown above, you can create modular and maintainable templates for your Go projects.

#go#programming#web-development

Share on:

Recommended

Copyright © EvolveDev. 2026 All Rights Reserved