Article directory
-
- Gin custom controller
-
- controller layering
- controller inheritance
- Gin middleware
-
- routing middleware
- c.Next() calls the remaining handlers for the request
- A route configures the execution order of multiple middleware
- global middleware
- Configure middleware in route grouping
- Data sharing between middleware and corresponding controllers
- Middleware Considerations
Gin custom controller
Controller layering
When the project is relatively large, it is necessary to group the controllers
Create a new controller in the root directory of the project, and create a new admin user … folder in the controller
Create a new indexController.go userController.go file in the admin file
indexController.go
package admin import "github.com/gin-gonic/gin" type IndexController struct {<!-- --> } func (con IndexController) Index(c *gin.Context) {<!-- --> c.String(200, "background page") }
userController.go
package admin import "github.com/gin-gonic/gin" type UserController struct {<!-- --> } func (con UserController) Index(c *gin.Context) {<!-- --> c.String(200, "User List") } func (con UserController) Add(c *gin.Context) {<!-- --> c.String(200, "User List---add") } func (con UserController) Edit(c *gin.Context) {<!-- --> c.String(200, "User List---edit") }
under the routes folder
Configure the corresponding route-adminRoutes.go
package routes import ( "Gin_demo/controllers/admin" "github.com/gin-gonic/gin" ) func AdminRoutesInit(r *gin.Engine) {<!-- --> adminRoutes := r. Group("/admin") {<!-- --> adminRoutes.GET("/", admin.IndexController{<!-- -->}.Index) adminRoutes.GET("/user", admin.UserController{<!-- -->}.Index) adminRoutes.GET("/user/add", admin.UserController{<!-- -->}.Add) adminRoutes.GET("/user/edit", admin.UserController{<!-- -->}.Edit) } }
Controller Inheritance
1. Create a new controller/admin/baseController.go
package admin import "github.com/gin-gonic/gin" type BaseController struct {<!-- --> } func (con BaseController) success(c *gin.Context) {<!-- --> c.String(200, "Success") } func (con BaseController) error(c *gin.Context) {<!-- --> c.String(200, "Failed") }
2. userController inherits baseController
package admin import "github.com/gin-gonic/gin" type UserController struct {<!-- --> BaseController } func (con UserController) Index(c *gin.Context) {<!-- --> //c.String(200, "User List") con. success(c) } func (con UserController) Add(c *gin.Context) {<!-- --> c.String(200, "User List---add") } func (con UserController) Edit(c *gin.Context) {<!-- --> c.String(200, "User List---edit") }
Gin middleware
Middleware is a series of operations performed before matching routes and after matching routes
Routing middleware
The middleware in Gin must be a gin.HandlerFunc type. When configuring the route, you can pass multiple func callback functions. The functions triggered before the last func callback function can be called middleware.
package main import ( "fmt" "github.com/gin-gonic/gin" "time" ) func InitMessage(c *gin.Context) {<!-- --> fmt.Println("111") } func main() {<!-- --> r := gin. Default() r.LoadHTMLGlob("templates/*") r.Static("/static", "./static") r.GET("/", InitMessage, func(c *gin.Context) {<!-- --> c.String(200, "Homepage") }) r.GET("/news", InitMessage, func(c *gin.Context) {<!-- --> c.String(200, "News") }) r.Run() }
c.Next() calls the remaining handlers for the request
Adding c.Next() to the middleware allows us to perform some operations after the route matching is completed
Count the execution time of a request
package main import ( "fmt" "github.com/gin-gonic/gin" "time" ) func InitMessage(c *gin.Context) {<!-- --> fmt.Println("111") start := time. Now(). Nanosecond() // call the remaining handlers for the request c. Next() end := time. Now(). Nanosecond() fmt.Println(end - start) } func main() {<!-- --> r := gin. Default() r.LoadHTMLGlob("templates/*") r.Static("/static", "./static") r.GET("/", InitMessage, func(c *gin.Context) {<!-- --> c.String(200, "Homepage") }) r.GET("/news", InitMessage, func(c *gin.Context) {<!-- --> c.String(200, "News") }) r.Run() }
A route configures the execution order of multiple middleware
When there are multiple middleware in a request, what is the execution order?
Various messages can be printed to the console to determine the order in which programs are executed.
package main import ( "fmt" "github.com/gin-gonic/gin" ) func InitMiddlewareOne(c *gin.Context) {<!-- --> fmt.Println("1") // call the remaining handlers for the request c. Next() fmt.Println("2") } func InitMiddlewareTwo(c *gin.Context) {<!-- --> fmt.Println("3") // call the remaining handlers for the request c. Next() fmt.Println("4") } func main() {<!-- --> r := gin. Default() r.LoadHTMLGlob("templates/*") r.Static("/static", "./static") r.GET("/", InitMiddlewareOne, InitMiddlewareTwo, func(c *gin.Context) {<!-- --> fmt.Println("Homepage...") c.String(200, "Homepage") }) r.GET("/news", InitMiddlewareOne, InitMiddlewareTwo, func(c *gin.Context) {<!-- --> c.String(200, "News") }) r.Run() }
Console content:
1 3 front page... 4 2
Global middleware
You can use r.Use(middleware name)
to define global middleware
package main import ( "fmt" "github.com/gin-gonic/gin" ) func InitMiddleware(c *gin.Context) {<!-- --> fmt.Println("1") // call the remaining handlers for the request c. Next() fmt.Println("2") } func main() {<!-- --> r := gin. Default() r.LoadHTMLGlob("templates/*") r.Static("/static", "./static") // define global middleware r.Use(InitMiddleware) r.GET("/", func(c *gin.Context) {<!-- --> fmt.Println("Homepage...") c.String(200, "Homepage") }) r.GET("/news", func(c *gin.Context) {<!-- --> c.String(200, "News") }) r.Run() }
Configure middleware in routing group
Create a new middlewares folder in the project root directory and create a new middleware
package middlewares import ( "fmt" "github.com/gin-gonic/gin" "time" ) func InitMiddleware(c *gin.Context) {<!-- --> fmt. Println(time. Now()) fmt.Println(c.Request.URL) }
Routing files in the routes file use middleware
package routes import ( "Gin_demo/controllers/admin" "Gin_demo/middlewares" "github.com/gin-gonic/gin" ) func AdminRoutesInit(r *gin.Engine) {<!-- --> // use middleware adminRoutes := r.Group("/admin", middlewares.InitMiddleware) {<!-- --> adminRoutes.GET("/", admin.IndexController{<!-- -->}.Index) adminRoutes.GET("/user", admin.UserController{<!-- -->}.Index) adminRoutes.GET("/user/add", admin.UserController{<!-- -->}.Add) adminRoutes.GET("/user/edit", admin.UserController{<!-- -->}.Edit) adminRoutes.GET("/article", admin.ArticleController{<!-- -->}.Index) adminRoutes.GET("/article/add", admin.ArticleController{<!-- -->}.Add) adminRoutes.GET("/article/edit", admin.ArticleController{<!-- -->}.Edit) } }
Share data between middleware and corresponding controller
Set value in middleware
package middlewares import ( "fmt" "github.com/gin-gonic/gin" "time" ) func InitMiddleware(c *gin.Context) {<!-- --> c. Set("username", "zhangsan") }
Get the value in the controller
package admin import ( "fmt" "github.com/gin-gonic/gin" ) type UserController struct {<!-- --> BaseController } func (con UserController) Index(c *gin.Context) {<!-- --> //c.String(200, "User List") //con. success(c) username, _ := c. Get("username") v, ok := username.(string) if ok {<!-- --> c. String(200, v) } else {<!-- --> c.String(200, "Failed to get user") } fmt.Println("username==>", username) } func (con UserController) Add(c *gin.Context) {<!-- --> c.String(200, "User List---add") } func (con UserController) Edit(c *gin.Context) {<!-- --> c.String(200, "User List---edit") }
Middleware Considerations
1. gin.Default() uses Logger and Recovery middleware by default, among which:
- Logger middleware writes logs to gin.DefaultWriter even if GIN_MODE=release is configured.
- Recovery middleware will recover any panic. If there is a panic, a 500 response code will be written.
If you don’t want to use the above two default middleware, you can use gin.New() to create a new route without any default middleware. Generally, gin.Default() is recommended.
2. When starting a new goroutine in middleware or handler, the original context (c *gin.Context) cannot be used, its read-only copy (c.Copy()) must be used
r.GET("/", func(c *gin.Context) {<!-- --> cCp := c.Copy() go func() {<!-- --> // simulate a long task with time. Sleep(). 5 seconds time. Sleep(5 * time. Second) // use the copy you created here fmt.Println("Done! in path " + cCp.Request.URL.Path) }() c.String(200, "Homepage") })