6. gin 中间件和路由
把请求的处理函数叫做中间件,且形参必须是*gin.Context
一个请求可以有多个中间件
通过Use()函数来调用中间件
6.1 单个路由和中间件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| type User struct { Name string Age int } func _set(c *gin.Context) { c.Set("note", "这是一条kv设置")
c.Set("user", User{ Name: "kjasn", Age: 11, }) } func main() { router := gin.Default()
router.Use(_set)
router.GET("/setVal", func(c *gin.Context) { note, ok := c.Get("note") if ok { fmt.Println(note) }
user, ok := c.Get("user") if ok { fmt.Println(user) c.JSON(http.StatusOK, gin.H{"data": user})
fmt.Println("断言") _user, ok := user.(User) if ok { fmt.Println("姓名:", _user.Name, "年龄:", _user.Age) c.JSON(http.StatusOK, gin.H{"name": _user.Name, "age": _user.Age}) } else { fmt.Println("断言失败,不是User类型") } } }) err := router.Run(":80") if err != nil { panic(err) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| type User struct { Name string Age int } func _set(c *gin.Context) { c.Set("note", "这是一条kv设置")
c.Set("user", User{ Name: "kjasn", Age: 11, }) } func main() { router := gin.Default()
router.Use(_set)
router.GET("/setVal", func(c *gin.Context) { note, ok := c.Get("note") if ok { fmt.Println(note) }
user, ok := c.Get("user") if ok { fmt.Println(user) c.JSON(http.StatusOK, gin.H{"data": user})
fmt.Println("断言") _user, ok := user.(User) if ok { fmt.Println("姓名:", _user.Name, "年龄:", _user.Age) c.JSON(http.StatusOK, gin.H{"name": _user.Name, "age": _user.Age}) } else { fmt.Println("断言失败,不是User类型") } } }) err := router.Run(":80") if err != nil { panic(err) } }
|
6.2 路由分组
将一系列的路由放到一个组下,统一管理,为分组路由定义全局中间件同单个路由定义全局中间件一样,用Use()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
type Response struct { Code int `json:"code"` Date any `json:"date"` Message string `json:"msg"` } type UserInfo struct { Name string `json:"name"` Age int `json:"age"` } type ArticleInfo struct { Title string `json:"title"` Content string `json:"content"` }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| func DisplayUserList(c *gin.Context) { list := []UserInfo{ {"张三", 23}, {"李四", 45}, }
c.JSON(http.StatusOK, Response{Code: 1, Date: list, Message: "请求成功"}) } func DisplayArticle(c *gin.Context) { list := []ArticleInfo { {"c语言入门到入土", "本书是c语言入门教程,面向入土"}, {"数据库从删库到跑路", "本书教你如何从删库到跑路"}, }
c.JSON(http.StatusOK, Response{Code: 1, Date: list, Message: "请求成功"}) } func showTest(c *gin.Context) { fmt.Println("showTest in ") c.JSON(http.StatusOK, gin.H{"msg": "这是一个用来测试的中间件"}) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| func UserRouterInit(api *gin.RouterGroup) { userManagement := api.Group("user-management") { userManagement.GET("/user", DisplayUserList) } }
func ArticleRouterInit(api *gin.RouterGroup) { article := api.Group("article-management") { article.GET("/article", DisplayArticle) } }
func Test(api *gin.RouterGroup) { test := api.Group("test").Use(showTest) { test.GET("show1", func(c *gin.Context) { fmt.Println("in show1") }) test.GET("show2", func(c *gin.Context) { fmt.Println("in show2") }) } }
|
- 在main()中分组然后直接调用拆分出来的包即可
分组之后,请求当前组下的其他分组需要加上父组的路径作为前缀 1 2 3 4 5 6
| api := router.Group("api") UserRouterInit(api) ArticleRouterInit(api) Test(api)
|
6.3 讲讲gin.Default()和gin.New()
gin.New() 是创建一个新的空白引擎,没有添加任何中间件。而**gin.Default()中调用了gin.New()并添加两个中间件 gin.Logger(), gin.Recovery(),这是二者的主要区别。 **
gin.Logger() : 记录请求日志:在每次请求到达服务器时,记录请求的信息,包括请求的方法(GET、POST 等)、请求的路径、请求的 IP 地址等。
gin.Recovery() : 恢复从错误中恢复:在处理请求时,捕获潜在的异常,比如代码出现了意外的错误或崩溃。它会确保应用不会因为异常而完全崩溃,而是尽量将异常信息记录下来,并返回一个友好的错误响应给客户端 。
1 2 3
| router := gin.New() router.Use(gin.Logger(), gin.Recovery())
|