Go embed: Embed your HTML frontend in Golang

Table of contents
Parsing HTML files into Go can be easy using the "html/template" package until the main file is moved somewhere else or errors arise because you did not use containers (or docker) when hosting the application. In Go 1.16, a package called embed
was introduced and it serves many purposes but mainly: embedding "anything" - strings, bytes, even files. This article explains how to use the embed package to insert HTML files into your golang application, build the golang app into an executable(.exe) file, and run that .exe file anywhere on your system without "HTML file not found" errors popping up.
Pre-requisites:
- Golang installed on your system
- basic knowledge of Golang
The finished project can be found here: finished project
Setup the project: - create a folder in your $GOPATH and name it go-embed
- cd into go-embed and run: go mod init go-embed`
- create the
main.go
inside the go-embed folder - create a folder
templates
, cd intotemplates
and create theindex.html
file
Updating the files:
For the index.html, we display a simple message.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Go Embed</title>
</head>
<body>
<h4>Go Embed: Embed HTML in Go</h4>
</body>
</html>
For the main.go file, we serve the HTML. I am using the default "net/http" package but you can use any package of your choice e.g. the "gorilla/mux" package.
main.go
:
package main
import (
"fmt"
"html/template"
"log"
"net/http"
)
func indexHandler(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("templates/index.html") // serving the index.html file
if err != nil {
log.Fatal(err)
}
tmpl.Execute(w, nil)
}
func main() {
http.HandleFunc("/", indexHandler)
fmt.Println("Server starting on port 8000!")
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal(err)
}
}
Run the application: go run main.go
Open our app on the browser:
Using the embed package:
In this section, we would embed the HTML file(index.html) in the Go binary which allows us to send the binary file anywhere and run that file without displaying any error.
Updating main.go
:
package main
import (
"embed"
"fmt"
"html/template"
"log"
"net/http"
)
//go:embed templates
var tplFolder embed.FS // embeds the templates folder into variable tplFolder
func indexHandler(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFS(tplFolder, "templates/index.html")
if err != nil {
log.Fatal(err)
}
println("Embedded the index.html file")
tmpl.Execute(w, nil)
}
func main() {
http.HandleFunc("/", indexHandler)
fmt.Println("Server starting on port 8000!")
err := http.ListenAndServe(":8000", nil)
if err != nil {
log.Fatal(err)
}
}
Run the application: go run main.go
Refresh the browser page:
Check the running application server:
We do not have any error, instead we have successfully embedded index.html.
Building the file:
First we stop the app server running.
Build the file by running: go build
We have a binary application:
Move the binary file somewhere else and run it:
./go-embed
for Linux/Mac or go-embed
for Windows.
Refresh the browser page:
Our app server:
Where can this embed feature be applied?
An example: Github
Here, I embedded all the HTML files which allow me to perform the authentication (registration or login) anywhere my application is even though the HTML files are not present. This makes hosting the application on Heroku or any hosting platform easier without getting file errors.
Subscribe to my newsletter
Read articles from Madukoma Blessed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Madukoma Blessed
Madukoma Blessed
A software engineer with 3+ years of experience, tasked with demystifying the amazing world of scalable, performant systems by designing, developing and maintaining high-quality, user-friendly services. Having worked on various projects ranging from startups to big tech enterprises, my interests lie in areas including data, software systems, technology, finance, customers and organizational success. As a skilled communicator and innovative engineer with an eye for detail, I excel in fast-paced environments. I find joy in collaborating with diverse teams of designers, engineers, and product managers, crafting tailored solutions that perfectly fit an organization's requirements.