More articles -> ISLAND

Having gained a basic understanding of Gin and the simple use of router, let’s use Gin to render our HTML pages.

Add the template

We are still working on the project in the previous chapter.

Start by creating a “templates” folder to hold our templates and create a new folder called index.tmpl. And write our template.


      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Gin Hello</title>
</head>
<body>
<main>{{ .title }}</main>
</body>
</html>
Copy the code

Tip GoLand doesn’t yet have the syntax for TMPL highlighting, so we can add the.tmpl suffix file to the Go Template. The method is as follows: file-settings-editor-file Types. (Or we can use *.gohtml directly as the template.)

We can load our template by LoadHTMLGlob and LoadHTMLFiles. LoadHTMLGlob method can load all templates in a directory, while LoadHTMLFiles will load only one file, its parameters are variable length parameters, we need to manually fill in the template file one by one. Here we use the LoadHTMLGlob method.

	router.LoadHTMLGlob("templates/*")
Copy the code

At this point we need to modify our/route to return our page template instead of a string.

Create a new indexHandler.go in handler to handle our/route.

func Index(context *gin.Context) {
	context.HTML(http.StatusOK, "index.tmpl", gin.H{
		"title": "hello gin " + strings.ToLower(context.Request.Method) + " method"})},Copy the code

When you visit our page, it’s still hello gin Get Method, but this is different from the string we returned earlier.

Open the browser -Network to see the difference between the two pages, one is text and the other is HTML

After writing the specific functionality, we need to revamp our unit tests. The original unit tests for the new interface logic are no longer feasible.

Rework the unit tests.

func TestIndexHtml(t *testing.T) {
	router := initRouter.SetupRouter()
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(http.MethodGet, "/".nil)
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
}
Copy the code

While unit testing, I found an error because I couldn’t find the HTML.

--- FAIL: TestIndexGetRouter (0.00 s)
panic: html/template: pattern matches no files: `templates/*` [recovered]
	panic: html/template: pattern matches no files: `templates/*`
Copy the code

At this point, I feel very strange, why the web page is perfectly accessible, but in the test is not accessible?

A lot of research has failed to find out why, and a lot of solutions are to write templates to a full path, which is obviously not a very good solution. There is little official talk of unit testing.

Here’s a way to do it:

We need to modify the method to load templates in different paths by checking for different schemas (debug,release,test).

initRouter.go

// Omit some code
    if mode := gin.Mode(); mode == gin.TestMode {
		router.LoadHTMLGlob(". /.. /templates/*")}else {
		router.LoadHTMLGlob("templates/*")}Copy the code

We also need to change test, so we’re going to write an init method, which is just like @before in Junit in Java

package test

import (
	"GinHello/initRouter"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

var router *gin.Engine

func init(a) {
	gin.SetMode(gin.TestMode)
	router = initRouter.SetupRouter()
}

func TestIndexHtml(t *testing.T) {
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(http.MethodGet, "/".nil)
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
	assert.Contains(t,w.Body.String(),"hello gin get method"."The HTML page returned should contain hello gin get Method")}Copy the code

This improves unit testing for future functional changes.

Adding a Static Resource

When the page is ready to display, we can add some static resources to make our page more beautiful. I chose Bootstrap 4 as the UI framework here. The Bootstrap 4 download

Jquery and Popper should also be introduced.

Let’s create a new Statics folder, unpack our Bootstrap, and copy our JS and CSS into the Statics folder.

In our initRouter, add static resources.

	router.Static("/statics"."./statics")
Copy the code

The new header. TMPL

{{ define "header" }}
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="#">Gin Hello</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item active">
                    <a class="nav-link" href="#">The home page<span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">The article lists</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link " href="#" tabindex="1" aria-disabled="true">about</a>
                </li>
            </ul>
            <form class="form-inline my-2 my-lg-0">
                <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success my-2 my-sm-0" type="submit">search</button>
            </form>
            <ul class="navbar-nav ">
                <li class="nav-item">
                    <a class="nav-link" href="#">The login</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">registered</a>
                </li>
            </ul>
        </div>
    </nav>
{{end}}
Copy the code

And add it to our index.tmpl

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="/statics/css/bootstrap.min.css">
    <link rel="stylesheet" href="/statics/css/bootstrap-grid.min.css">
    <link rel="stylesheet" href="/statics/css/bootstrap-reboot.min.css">
    <script src="/statics/js/jquery.min.js" rel="script"></script>
    <script src="/statics/js/Popper.js" rel="script"></script>
    <script rel="script" src="/statics/js/bootstrap.bundle.js"></script>
    <title>Gin Hello</title>
</head>
<body>
<header>
    {{template "header"}}
</header>
<main>
    {{ .title }}
</main>
</body>
Copy the code

Now run our website and the image below appears.

Adding a Website icon

All we need is an icon.

The site also lacks the site icon at this time, which is also set by the functions given by Gin. We put the.ico image in the project root directory and set it in initRouter.

	router.StaticFile("/favicon.ico"."./favicon.ico")
Copy the code

Run our site again and you’ll see the icon in the top left TAB of the site.

Code for this section

Github