41

Gin(三):配合模板 tmpl

 4 years ago
source link: https://www.tuicool.com/articles/Vry6BnA
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

更多文章 狂点 -> ISLAND

前面的学习已经对 Gin 有了一个初步的认识和了解,对 router 的简单使用也有了一定的掌握,那么今天就来使用 Gin 来渲染出我们的 html 页面吧。

添加模板

我们仍旧是在上一章节的项目中进行修改。

首先新建一个 templates 文件夹,用于存放我们的模板文件,在文件夹中新建立 index.tmpl 。并且编写我们的模板。

<!doctype html>
<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>
复制代码

小提示GoLand 现在还未对 tmpl 有高亮显示语法,我们可以将 .tmpl 后缀文件添加到 go Template 模板。方法如下: File-settings-Editor-File Types 。(或者我们直接使用 *.gohtml 做为模板也是可以的)如图:

UbuEfem.jpg!web

我们可以通过 LoadHTMLGlobLoadHTMLFiles 两个方法来对我们的模板进行加载。其中 LoadHTMLGlob 方法可以将一个目录下所有的模板进行加载,而 LoadHTMLFiles 只会加载一个文件,他的参数为可变长参数,需要我们一个一个的手动将模板文件填写。这里我们使用 LoadHTMLGlob 方法。

router.LoadHTMLGlob("templates/*")
复制代码

此时我们需要修改我们的 / 路由了,不再是让它返回一个字符串,而是返回我们的页面模板。

handler 中新建立一个 indexHandler.go ,用来处理我们的 / 路由。

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

此时在访问我们的页面,仍旧是 hello gin get method ,但是这和我们之前返回的字符串是不同的。

打开 浏览器-Network 就可以看到这两个页面的不同,一个是 text 一个是 html

yAR7VjV.jpg!web

写完具体功能,我们需要改造一下我们的单元测试,针对新的接口逻辑原有的单元测试已经行不通了。

重新修改单元测试。

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)
}
复制代码

进行单元测试的时候,发现报错了,报错原因是竟然是找不到 html

--- FAIL: TestIndexGetRouter (0.00s)
panic: html/template: pattern matches no files: `templates/*` [recovered]
	panic: html/template: pattern matches no files: `templates/*`
复制代码

此时就感到很奇怪了,为什么网页上可以很好的访问到,在测试中却无法访问呢?

查了很多资料没有找到原因,很多解决方法是将 templates 写成全路径,这显然不是很好的解决方法。官方对于单元测试介绍少的可怜。

这里我介绍一种方法:

我们需要修改方法,通过判断不同的模式( debug , release , test )来加载不同路径下的 templates

initRouter.go

// 省略部分代码	
    if mode := gin.Mode(); mode == gin.TestMode {
		router.LoadHTMLGlob("./../templates/*")
	} else {
		router.LoadHTMLGlob("templates/*")
	}
复制代码

同时,也需要修改 test ,我们要写个 init 方法,这里的 init 方法就好比 javaJunit 中的 @Before

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() {
	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","返回的HTML页面中应该包含 hello gin get method")
}
复制代码

这样完善了单元测试,方便日后的功能更改。

添加静态资源

当网页可以正常显示的时候,我们可以添加一些静态资源来使我们的页面更加美观。我在这里选择了 Bootstrap 4 做为一个 UI 界面框架。 Bootstrap 4 下载

同时还要引入 JqueryPopper

我们新建一个 statics 文件夹,将我们 Bootstrap 解压,将 jscss 复制到 statics 目录下。

在我们的 initRouter 中,对静态资源进行添加。

router.Static("/statics","./statics")
复制代码

新建 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="#">主页 <span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">文章列表</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link " href="#" tabindex="-1" aria-disabled="true">关于</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">搜索</button>
            </form>
            <ul class="navbar-nav ">
                <li class="nav-item">
                    <a class="nav-link" href="#">登录</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">注册</a>
                </li>
            </ul>
        </div>
    </nav>
{{end}}
复制代码

并在我们的 index.tmpl 上进行添加

<body>
<header>
    {{template "header"}}
</header>
<main>
    {{ .title }}
</main>
</body>
复制代码

此时运行我们的网站,出现下图样式。

IfuAray.jpg!web

添加网站图标

万事俱备,只欠一个 icon

网站此时还缺少网站的图标,网站图标也是通过 Gin 给定的函数设置。我们将 .ico 图片放到项目根目录下,然后在 initRouter 中设置。

router.StaticFile("/favicon.ico","./favicon.ico")
复制代码

再次运行我们的网站,此时就会发现网站的左上角标签页中出现了设置好的图标。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK