网站性质,制作公司网页的步骤,文化公司做网站交文化事业费吗,wordpress模板建站对控制器的分组与继承 1 #xff09;设计项目目录结构
yourGinProject/ 根目录├── go.mod go mod 文件├── go.sum go sum 文件├── main.go main 文件└── tpls html模板目录│ └── web│ │ └── index.html├── routers 路由目录│ …对控制器的分组与继承 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.go2 主程序 main.go
package mainimport (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 }}h1web index 页面/h1{{.msg}}{{ end }}4 ) routers 配置
4.1 webRouters.go
package routersimport (gin-demo/controllers/webgithub.com/gin-gonic/gin
)func WebRoutersInit(r *gin.Engine) {webRouters : r.Group(/){webRouters.GET(/, web.WebCtrl{}.Index)}
}4.2 apiRouters.go
package routersimport (gin-demo/controllers/apigithub.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 routersimport (gin-demo/controllers/admingithub.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 webimport (net/httpgithub.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 apiimport (github.com/gin-gonic/ginnet/http
)type ApiCtrl struct{}func (con ApiCtrl) Index(c *gin.Context) {c.String(http.StatusOK, api接口总承)
}
func (con ApiCtrl) User(c *gin.Context) {c.String(http.StatusOK, 这是一个 user 接口)
}5.3 admin/indexCtrl.go
package adminimport (github.com/gin-gonic/ginnet/http
)type IndexCtrl struct {}func (con IndexCtrl) Index(c *gin.Context) {c.String(http.StatusOK, admin 页面)
}5.4 admin/baseCtrl.go
package adminimport (github.com/gin-gonic/ginnet/http
)type BaseCtrl struct{}func (con BaseCtrl) success(c *gin.Context) {c.String(http.StatusOK, 成功)
}func (con BaseCtrl) error(c *gin.Context) {c.String(http.StatusOK, 失败)
}5.4 admin/userCtrl.go
package adminimport (github.com/gin-gonic/ginnet/http
)type UserCtrl struct {BaseCtrl
}func (con UserCtrl) Index(c *gin.Context) {c.String(http.StatusOK, 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 mainimport (fmttimegithub.com/gin-gonic/ginnet/http
)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(http.StatusOK, 首页)})r.GET(/news, initMiddleware, func(c *gin.Context) {c.String(http.StatusOK, 新闻页面)})r.Run()
}中间件就是匹配路由前和匹配路由完成后执行的一系列操作中间件必须是一个 gin.HandlerFunc 类型
2 多个路由中间件
package mainimport (fmttimegithub.com/gin-gonic/ginnet/http
)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()// 终止调用该请求的剩余处理程序// c.Abort() // 注意Next 和 Abort 只能二选一可以控制在某些情况下终止中间件fmt.Println(第2个中间件结束)
}func main() {// 创建一个默认的路由引擎r : gin.Default()r.GET(/, initMiddleware, initMiddleware2, func(c *gin.Context) {c.String(http.StatusOK, 首页)})r.GET(/news, initMiddleware, initMiddleware2, func(c *gin.Context) {c.String(http.StatusOK, 新闻页面)})r.Run()
}上述示例中有两个中间件就是 initMiddleware, initMiddleware2访问路由时的输出顺序第1个中间件开始
第2个中间件开始
第2个中间件结束
第1个中间件结束并统计其处理时间 21000这种就是洋葱模型基本上所有中间件都符合这一模型配置路由的时候可以传递多个 func 回调函数最后一个 func 回调函数前面触发的方法都可以称为中间件中间件里面加上 ctx.Next()可以让我们在路由匹配完成后执行一些操作如果想要终止中间件操作可以通过判断添加 ctx.Abort() 来终止接下来的操作
3 全局中间件
package mainimport (fmttimegithub.com/gin-gonic/ginnet/http
)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(http.StatusOK, 首页)})r.GET(/news, func(c *gin.Context) {c.String(http.StatusOK, 新闻页面)})r.Run()
}这种属于全局配置的中间件不用在每个路由中书写进行全局use这种写法和第2种效果一致
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 middlewaresimport (fmttimegithub.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 routersimport (gin-demo/controllers/admingithub.com/gin-gonic/gingin-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 做数据统计下面在 admin.userCtrl 中获取中间件中配置的值
改造 controllers/admin/userCtrl.go 文件
package adminimport (net/httpgithub.com/gin-gonic/gin
)type UserCtrl struct {BaseCtrl
}func (con UserCtrl) Index(c *gin.Context) {username, _ : c.Get(username) // 这里从中间件中读取数据c.String(http.StatusOK, user 页面: %v, username) // 响应出去
}
func (con UserCtrl) Success(c *gin.Context) {con.success(c)
}
func (con UserCtrl) Error(c *gin.Context) {con.error(c)
}这样就可以获取到中间件中读取的数据了
注意事项
gin 默认中间件 gin.Default()默认使用了 Logger 和 Recovery 中间件其中Logger 中间件将日志写入 gin.DefaultWriter即使配置了 GIN_MODEreleaseRecovery 中间件会 recover 任何 panic。如果有 panic 的话会写入 500 响应码如果不想使用上面两个默认的中间件可以使用 gin.New() 新建一个没有任何默认中间件的路由 gin 中间件中使用 goroutine 当在中间件或 handler 中启动新的 goroutine 时不能使用原始的上下文c *gin.Context必须使用其只读副本c.Copy()