1 )设计项目目录结构
yourGinProject/ ······························· 根目录
├── go.mod ·································· go mod 文件
├── go.sum ·································· go sum 文件
├── main.go ································· main 文件
└── tpls ····································· html模板目录
│ └── web
│ │ └── index.html
├── routers ·································· 路由目录
│ ├── webRouters.go
│ ├── apiRouters.go
│ └── adminRouters.go
├── controllers ······························ 控制器目录
│ ├── web
│ │ └── webCtrl.go
│ ├── api
│ │ └── apiCtrl.go
│ └── admin
│ │ ├── base.go
│ │ ├── indexCtrl.go
│ │ └── userCtrl.go
2 )主程序 main.go
package main
import (
"gin-demo/routers" //gin-demo 是 go mod init 初始化的工程,下同
"github.com/gin-gonic/gin"
)
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
//加载模板 放在配置路由前面
r.LoadHTMLGlob("tpls/**/*")
routers.WebRoutersInit(r)
routers.ApiRoutersInit(r)
routers.AdminRoutersInit(r)
r.Run()
}
3 ) HTML模板目录配置
tpls/web/index.html
{{ define "web/index.html" }}
<h1>web index 页面h1>
{{.msg}}
{{ end }}
4 ) routers 配置
4.1 webRouters.go
package routers
import (
"gin-demo/controllers/web"
"github.com/gin-gonic/gin"
)
func WebRoutersInit(r *gin.Engine) {
webRouters := r.Group("/")
{
webRouters.GET("/", web.WebCtrl{}.Index)
}
}
4.2 apiRouters.go
package routers
import (
"gin-demo/controllers/api"
"github.com/gin-gonic/gin"
)
func ApiRoutersInit(r *gin.Engine) {
apiRouters := r.Group("/api")
{
apiRouters.GET("/", api.ApiCtrl{}.Index)
apiRouters.GET("/user", api.ApiCtrl{}.User)
}
}
4.2 adminRouters.go
package routers
import (
"gin-demo/controllers/admin"
"github.com/gin-gonic/gin"
)
func AdminRoutersInit(r *gin.Engine) {
adminRouters := r.Group("/admin")
{
adminRouters.GET("/", admin.IndexCtrl{}.Index)
adminRouters.GET("/user", admin.UserCtrl{}.Index)
adminRouters.GET("/user/success", admin.UserCtrl{}.Success)
adminRouters.GET("/user/error", admin.UserCtrl{}.Error)
}
}
5 ) controller 配置
5.1 web/webCtrl.go
package web
import (
"net/http"
"github.com/gin-gonic/gin"
)
type WebCtrl struct{}
func (con WebCtrl) Index(c *gin.Context) {
c.HTML(http.StatusOK, "web/index.html", gin.H{
"msg": "我是一个msg",
})
}
5.2 api/apiCtrl.go
package api
import "github.com/gin-gonic/gin"
type ApiCtrl struct{}
func (con ApiCtrl) Index(c *gin.Context) {
c.String(200, "api接口总承")
}
func (con ApiCtrl) User(c *gin.Context) {
c.String(200, "这是一个 user 接口")
}
5.3 admin/indexCtrl.go
package admin
import "github.com/gin-gonic/gin"
type IndexCtrl struct {}
func (con IndexCtrl) Index(c *gin.Context) {
c.String(200, "admin 页面")
}
5.4 admin/baseCtrl.go
package admin
import "github.com/gin-gonic/gin"
type BaseCtrl struct{}
func (con BaseCtrl) success(c *gin.Context) {
c.String(200, "成功")
}
func (con BaseCtrl) error(c *gin.Context) {
c.String(200, "失败")
}
5.4 admin/userCtrl.go
package admin
import "github.com/gin-gonic/gin"
type UserCtrl struct {
BaseCtrl
}
func (con UserCtrl) Index(c *gin.Context) {
c.String(200, "user 页面")
}
func (con UserCtrl) Success(c *gin.Context) {
con.success(c)
}
func (con UserCtrl) Error(c *gin.Context) {
con.error(c)
}
以上就是对控制器的一般文件拆分和继承关系的调用示例,验证如下
/
访问首页
/api
/api/user
/admin
/admin/user
/admin/user/success
/admin/user/error
以上均可正常访问,这样就可以最快完成一个项目的拆分
1 ) 基础用法, 单一中间件
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
func initMiddleware(c *gin.Context) {
// 记录开始时间
start := time.Now().UnixNano()
// 调用该请求的剩余处理程序
c.Next()
// 记录结束时间
end := time.Now().UnixNano()
// 输出当前渲染时间差
fmt.Println("时间:", end - start)
}
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
r.GET("/", initMiddleware, func(c *gin.Context) {
c.String(200, "首页")
})
r.GET("/news", initMiddleware, func(c *gin.Context) {
c.String(200, "新闻页面")
})
r.Run()
}
2 )多个路由中间件
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
func initMiddleware(c *gin.Context) {
fmt.Println("第1个中间件开始")
// 记录开始时间
start := time.Now().UnixNano()
// 调用该请求的剩余处理程序
c.Next()
// 记录结束时间
end := time.Now().UnixNano()
// 输出当前渲染时间差
fmt.Println("第1个中间件结束,并统计其处理时间:", end - start)
}
func initMiddleware2(c *gin.Context) {
fmt.Println("第2个中间件开始")
c.Next()
fmt.Println("第2个中间件结束")
}
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
r.GET("/", initMiddleware, initMiddleware2, func(c *gin.Context) {
c.String(200, "首页")
})
r.GET("/news", initMiddleware, initMiddleware2, func(c *gin.Context) {
c.String(200, "新闻页面")
})
r.Run()
}
第1个中间件开始
第2个中间件开始
第2个中间件结束
第1个中间件结束,并统计其处理时间: 21000
3 )全局中间件
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
func initMiddleware(c *gin.Context) {
fmt.Println("第1个中间件开始")
// 记录开始时间
start := time.Now().UnixNano()
// 调用该请求的剩余处理程序
c.Next()
// 记录结束时间
end := time.Now().UnixNano()
// 输出当前渲染时间差
fmt.Println("第1个中间件结束,并统计其处理时间:", end - start)
}
func initMiddleware2(c *gin.Context) {
fmt.Println("第2个中间件开始")
c.Next()
fmt.Println("第2个中间件结束")
}
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// 全局中间件
r.Use(initMiddleware, initMiddleware2)
r.GET("/", func(c *gin.Context) {
c.String(200, "首页")
})
r.GET("/news", func(c *gin.Context) {
c.String(200, "新闻页面")
})
r.Run()
}
4 )中间件的拆分
yourGinProject/ ······························· 根目录
├── go.mod ·································· go mod 文件
├── go.sum ·································· go sum 文件
├── main.go ································· main 文件
└── tpls ····································· html模板目录
│ └── web
│ │ └── index.html
├── routers ·································· 路由目录
│ ├── webRouters.go
│ ├── apiRouters.go
│ └── adminRouters.go
├── controllers ······························ 控制器目录
│ ├── web
│ │ └── webCtrl.go
│ ├── api
│ │ └── apiCtrl.go
│ └── admin
│ │ ├── base.go
│ │ ├── indexCtrl.go
│ │ └── userCtrl.go
├── middlewares ······························ 中间件目录
│ └── init.go
这里使用最顶层控制器拆分时用的结构
这里 middlewares/init.go
package middlewares
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
func InitMiddleware(c *gin.Context) {
//判断用户是否登录
fmt.Println("当前时间:", time.Now())
fmt.Println("当前URL:", c.Request.URL)
c.Set("username", "Wang")
// 定义一个 goroutine 统计日志
// 当在中间件或 handler 中启动新的 goroutine 时
// 不能使用原始的上下文(c *gin.Context), 必须使用其只读副本(c.Copy())
cCp := c.Copy()
go func() {
time.Sleep(2 * time.Second)
fmt.Println("Done! in path " + cCp.Request.URL.Path)
}()
}
改造 routers/adminRouters.go 文件
package routers
import (
"gin-demo/controllers/admin"
"github.com/gin-gonic/gin"
"gin-demo/middlewares" // 引入
)
func AdminRoutersInit(r *gin.Engine) {
adminRouters := r.Group("/admin", middlewares.InitMiddleware) // 注意这里
{
adminRouters.GET("/", admin.IndexCtrl{}.Index)
adminRouters.GET("/user", admin.UserCtrl{}.Index)
adminRouters.GET("/user/success", admin.UserCtrl{}.Success)
adminRouters.GET("/user/error", admin.UserCtrl{}.Error)
}
}
在 /admin
及子路由被访问时都会经过这个中间件
这里用了一个 goroutine 做数据统计