Creating Reusable Templates
Our application will display a web page using its template. However, there will be several parts such as the header, menu, sidebar, and footer, which will be common across all pages. Go allows us to create reusable template snippets that can be imported in other templates.
The header and the footer will be the common pieces that will be reused across all templates. We will also create the menu in its own template file which will be used by the header template. Finally, we'll create the template for the index page which will import the header and the footer. All the template files will be placed in the templates
directory within the project directory.
Let's start by creating the template for the menu in templates/menu.html
as follows:
<!--menu.html-->
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">
Home
</a>
</div>
</div>
</nav>
Initially, the menu contains only the link to the home page. We will add to this as we add more functionality to the application. The template for the header will be placed in the templates/header.html
file as follows:
<!--header.html-->
<!doctype html>
<html>
<head>
<!--Use the `title` variable to set the title of the page-->
<title>{{ .title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<!--Use bootstrap to make the application look nice-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script async src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
</head>
<body class="container">
<!--Embed the menu.html template at this location-->
{{ template "menu.html" . }}
As you can see, we are using the open source Bootstrap framework. Most of this file is standard HTML. However, take note of two lines. The line containing <title>{{ .title }}</title>
is used to dynamically set the title of the page using the .title
variable that must be set inside the application. Secondly, the line containing {{ template "menu.html" . }}
is used to import the menu template from the menu.html
file. This is how Go lets you import one template in another.
The template for the footer contains static HTML. The template for the index page makes use of the header and the footer and displays a simple Hello Gin message:
<!--index.html-->
<!--Embed the header.html template at this location-->
{{ template "header.html" .}}
<h1>Hello Gin!</h1>
<!--Embed the footer.html template at this location-->
{{ template "footer.html" .}}
Like the index template, templates for other pages will reuse the templates for the header and the footer in a similar manner.
Completing and Validating the Setup
Once you have created the templates, it's time to create the entry file for your application. We'll create the main.go
file for this with the simplest possible web application that will use the index template. We can do this using Gin in four steps:
1. Create the router
The default way to create a router in Gin is as follows:
router := gin.Default()
This creates a router which can be used to define the build of the application.
2. Load the templates
Once you have created the router, you can load all the templates like this:
router.LoadHTMLGlob("templates/*")
This loads all the template files located in the templates
folder. Once loaded, these don't have to be read again on every request making Gin web applications very fast.
3. Define the route handler
At the heart of Gin is how you divide the application into various routes and define handlers for each route. We will create a route for the index page and an inline route handler.
router.GET("/", func(c *gin.Context) {
// Call the HTML method of the Context to render a template
c.HTML(
// Set the HTTP status to 200 (OK)
http.StatusOK,
// Use the index.html template
"index.html",
// Pass the data that the page uses (in this case, 'title')
gin.H{
"title": "Home Page",
},
)
})
The router.GET
method is used to define a route handler for a GET request. It takes in as parameters the route (/
) and one or more route handlers which are just functions.
The route handler has a pointer to the context (gin.Context
) as its parameter. This context contains all the information about the request that the handler might need to process it. For example, it includes information about the headers, cookies, etc.
The Context also has methods to render a response in HTML, text, JSON and XML formats. In this case, we use the context.HTML
method to render an HTML template (index.html
). The call to this method includes additional data in which the value of title
is set to Home Page
. This is a value that the HTML template can make use of. In this case, we use this value in the <title>
tag in the header's template.
4. Start the application
To start the application, you can use the Run
method of the router:
router.Run()
This starts the application on localhost
and serves on the 8080
port by default.
The complete main.go
file looks as follows:
// main.go
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
var router *gin.Engine
func main() {
// Set the router as the default one provided by Gin
router = gin.Default()
// Process the templates at the start so that they don't have to be loaded
// from the disk again. This makes serving HTML pages very fast.
router.LoadHTMLGlob("templates/*")
// Define the route for the index page and display the index.html template
// To start with, we'll use an inline route handler. Later on, we'll create
// standalone functions that will be used as route handlers.
router.GET("/", func(c *gin.Context) {
// Call the HTML method of the Context to render a template
c.HTML(
// Set the HTTP status to 200 (OK)
http.StatusOK,
// Use the index.html template
"index.html",
// Pass the data that the page uses (in this case, 'title')
gin.H{
"title": "Home Page",
},
)
})
// Start serving the application
router.Run()
}
To execute the application from the command line, go to your application directory and execute the following command:
go build -o app
This will build your application and create an executable named app
which you can run as follows:
./app
If all goes well, you should be able to access your application at http://localhost:8080
and it should look like this:
The directory structure of your application at this stage should be as follows:
├── main.go
└── templates
├── footer.html
├── header.html
├── index.html
└── menu.html