Gin 的路由其实就是 Java 中 @RequestMapping
注解的内容,只是 Go 需要在一个代码模块中统一对所有路由进行配置。
全文链接:https://blog.nineya.com/archives/150.html
一、路由组配置
一般情况下,通过路由需要完成两个事情,一是通过 HTML 模板完成前端页面的渲染,二是实现 Api 接口调用。
这两部分功能是完全不一样的,在 Gin 中可以用两个不同的路由组来隔离逻辑。
go
router := gin.Default()
// 指定模板文件所在的路径
router.LoadHTMLGlob("templates/*.html")
// 渲染html的路由组
htmlGroup := router.Group("")
// api 处理的路由组
apiGroup := router.Group("api")
再更近一步,可以将 API 路由组再细分为公共 API 和私有 API。
go
// 公共API路由组
publicGroup := apiGroup.Group("public")
// 私有API路由组,绑定鉴权中间件
privateGroup := apiGroup.Group("")
privateGroup.Use(middleware.AdminAuth)
二、API 接口实现
创建一个简单的 GET 接口,并返回一条字符串数据内容。
go
apiGroup.GET("/health", func(c *gin.Context) {
c.String(200, "ok health")
})
返回一个 JSON 数据:
go
apiGroup.GET("/health", func(c *gin.Context) {
c.AbortWithStatusJSON(200, map[string]string{"msg": "ok health"})
})
三、HTML 模板渲染
渲染模板用的是 Go 内置的 html.template
工具包,Gin 对该工具包进行了集成,在渲染 Html 模板前需要先在 *gin.Engine
路由上指定模板文件所在的位置。
必须在
*gin.Engine
路由上指定,不能在路由组上指定。
有两个方法可以指定模板位置:
router.LoadHTMLGlob
函数可以指定一个路径,模糊匹配下的模板文件。
go
// 指定模板所在的目录
router.LoadHTMLGlob("templates/*")
// 指定模板文件为html文件
router.LoadHTMLGlob("templates/*.html")
// 当模板在多级目录下时
router.LoadHTMLGlob("templates/**/*.html")
router.LoadHTMLFiles
函数用于直接指定模板文件名称,可以同时指定多个文件。
go
router.LoadHTMLFiles("templates/index.html", "templates/page/index.html")
模板接口:
通过如下方法就可以指定渲染模板。
go
htmlGroup.GET("/index.html", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "玖涯菜菜子",
})
})
四、HTML 模板的缺陷
通过章节三的方法可以实现模板,但是这个方法是存在一些问题的,或者说是存在一些限制。因为 Gin 只是简单集成了这个模板框架,并没有怎么考虑一些细节问题。
4.1 模板访问问题
注册了 templates/page/index.html
模板,但是通过 templates/page/index.html
或者 page/index.html
会发现访问不到模板,只能通过 index.html
访问。
原因: 在注册模板时以文件名作为模板名称,所以c.HTML函数中只要模板文件名,不带模板所在的目录。如果不同目录出现多个同名文件,模板将相互覆盖。
如上例子中,router.LoadHTMLFiles("templates/index.html", "templates/page/index.html")
这两个文件中,templates/index.html
文件会被覆盖的。
解决方法: 在模板中通过 define
关键字为模板中的代码片断赋予一个新名称,然后通过这个名称访问模板。
go
{{ define "test/index.html" }}
test
{{ end }}
4.2 多次注册模板只有最后一次注册能生效
执行了多次 router.LoadHTMLGlob
或 router.LoadHTMLFiles
函数,只有最后一次注册的内容能够生效。
原因: 每执行一次上面的方法都会重置 Gin 的 HTMLRender
属性,而这个属性存储着模板信息,所以每一次调这个函数都会重置模板状态。
解决方法: 通过官方接口无法解决,需要自己继承 HTMLRender
写一个 HTML 渲染的接口实现,在一个章节细说。
4.3 LoadHTMLGlob 指定多级目录会报错
原因: 使用 **/*
这种方式指定了两级目录,如果不存在两级目录,程序运行将会出错。
解决方法: 通过官方的接口无法解决,可自己继承 HTMLRender
写一个 HTML 渲染的接口解决。
以上问题可通过继承 HTMLRender
自定义 Gin 的模板渲染工具解决,小玖在后面的章节中详细介绍。