likes
comments
collection
share

Gin框架完全使用指南 | Gin如何创建路由

作者站长头像
站长
· 阅读数 4

公众号:程序员读书,欢迎关注

在上一篇文章中,我们已经学会了如何使用Gin框架启动一个Web服务器,但如果要接收并处理HTTP请求,则还需要设置路由。

什么是路由

Web开发中,路由用于指定一个Web接口被请求的路径(path)以及接收请求的方法(如POSTGET等)。

路由配置

Gin框架中,我们可以按照HTTP请求方法进行路由分配,对于有共同前缀的路由还可以使用路由分组来简化路由的设置,甚至可以使用通配符匹配某一模式的路由。

简单路由

创建gin.Engne对象后,可以调用gin.Engine对象的GET等方法分配路由处理HTTP请求:

 package main
 ​
 import "github.com/gin-gonic/gin"
 ​
 func main() {
   //创建gin.Engine
   engine := gin.Default()
 ​
   //GET请求
   engine.GET("/myGet", func(ctx *gin.Context) {
     //业务处理逻辑
   })
   //POST请求
   engine.POST("/myPost", func(ctx *gin.Context) {})
   //PUT请求
   engine.PUT("/myPut", func(ctx *gin.Context) {})
   //DELETE请求
   engine.DELETE("/myDelete", func(ctx *gin.Context) {})
   //PATCH请求
   engine.PATCH("/myPatch", func(ctx *gin.Context) {})
   //HEAD请求
   engine.HEAD("/myHead", func(ctx *gin.Context) {})
   //OPTIONS请求
   engine.OPTIONS("/myOptions", func(ctx *gin.Context) {})
 ​
   engine.Run()
 }

从上面的示例可以看到,处理对应路由的函数签名为:

 func(ctx *gin.Context) {}

实际,在设置路由时,也可以同时添加多个处理函数:

   engine.GET("/myGet", func(ctx *gin.Context) {
     //中间件
     ctx.Next()
   },func(ctx *gin.Context){
     //业务处理逻辑
   })

如果一个路由添加了多个处理函数,本质上是添加中间件,因此前面的处理函数必须Next()方法才会执行下一个处理函数。

除了以上与HTTP请求方法一一对应的几外方法,还可以通过下面三个方法进行路由设置:

 Any(relativePath string, handlers ...HandlerFunc) IRoutes
 Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes
 Match(methods []string, relativePath string, handlers ...HandlerFunc) IRoutes
  • Any()方法设置的路由对任何HTTP请求方法都有效。
  • 调用Handle()方法设置路由时,则需要自己指定HTTP请求方法。
  • 如果只针对某几个HTTP请求设置路由,可以调用Match()方法。
 package main
 ​
 import "github.com/gin-gonic/gin"
 ​
 func main() {
 ​
   engine := gin.New()
   //可以接收GET,POST等任意方式的请求
   engine.Any("/about", func(ctx *gin.Context) {})
   //自己指定接收GET请求
   engine.Handle("GET", "/user/info", func(ctx *gin.Context) {})
   //只允许GET或者POST
   engine.Match([]string{"GET", "POST"}, "/user/edit", func(ctx *gin.Context) {})
   
   engine.Run()
 }

路由分组

如果多个路由有共同的前缀,一个个设置可能会比较麻烦,如:

 engine.GET("/dashboard/user/list", func(ctx *gin.Context) {})
 engine.POST("/dashboard/user/edit",func(ctx *gin.Context) {})
 engine.POST("/dashboard/user/add",func(ctx *gin.Context) {})
 engine.GET("/dashboard/user/delete",func(ctx *gin.Context) {})
 ​
 engine.POST("/dashboard/order/add",func(ctx *gin.Context) {})
 engine.GET("/dashboard/order/delete",func(ctx *gin.Context) {})
 ​
 engine.GET("/api/user/profile",func(ctx *gin.Context) {})
 engine.GET("/api/user/setting",func(ctx *gin.Context) {})
 ​
 engine.GET("/api/creator/home",func(ctx *gin.Context) {})
 engine.GET("/api/creator/article",func(ctx *gin.Context) {})

Gin框架支持对路由进行分组,同一个分组的路由拥有共同的路由前缀,因此上面的路由设置可以采用路由分组的形式进行划分:

 func main() {
   engine := gin.Default()
 ​
   //分组:dashboard
   dashboard := engine.Group("/dashboard")
   {
     user := engine.Group("/user")
     {
       user.GET("/user/list", func(ctx *gin.Context) {})
       user.POST("/user/edit", func(ctx *gin.Context) {})
       user.POST("/user/add", func(ctx *gin.Context) {})
       user.GET("/user/delete", func(ctx *gin.Context) {})
     }
     order := engine.Group("order")
     {
       order.POST("/user/add", func(ctx *gin.Context) {})
       order.GET("/user/delete", func(ctx *gin.Context) {})
     }
   }
 ​
   //分组:api
   api := router.Group("/api")
   {
     user := api.Group("/user")
     {
       user.GET("/profile", func(ctx *gin.Context) {})
       user.GET("/setting", func(ctx *gin.Context) {})
     }
     
     creator := api.Group("/creator")
     {
       creator.GET("/home", func(ctx *gin.Context) {})
       creator.GET("/article", func(ctx *gin.Context) {})
     }
   }
   router.Run()
 }

上面的示例中包含子路由的花括号({})不是必须的,只是为了划分代码层次以便更好地阅读。

通配符

Gin路由除了是普通字符串外,还可以是通配符:*

 package main
 ​
 import "github.com/gin-gonic/gin"
 ​
 func main() {
 ​
   router := gin.New()
 ​
   router.GET("/user/*name", func(ctx *gin.Context) {})
   router.GET("/goods/:id", func(ctx *gin.Context) {})
 }

通配符使用限制

通配符后面必须有一个名称,因此下面的用法是错误的:

/user/*
/order/:

正确的用法是通配符后面必须有一个名称:

/user/*name
/order/:id

同一级路由不能有两个路由,因此下面的用法是错误:

/user/::id
/user/**name

通配符*只能放在最后一级路由:

# 错误用法
/dashbaord/*/goods/
# 正确
/dashboard/*

设置了*通配符之后,如果在同一级路由设置其他的路由,Gin框架会认为路由重复:

# 由于有*通配符,因此同一级不能再设置路由
/dashobard/edit
/dashboard/*

对于:通配符,同一级路由也只能设置一个:

# 错误用法,即使名称不同,也只能设置一个
/user/:id
/user/:name

注意:路由重复是在同一种HTTP请求方法内才有的限制,在上面的例子中,如果/user/:id用于GET请求,而/user/:name用于POST请求,则不会有这样的限制:

package main

func main(){

  router := gin.New()

  //错误
  router.GET("/user/:name", func(ctx *gin.Context) {})
	router.GET("/user/:id", func(ctx *gin.Context) {})
  
  //正确
  router.GET("/goods/:name", func(ctx *gin.Context) {})
	router.POST("/goods/:id", func(ctx *gin.Context) {})
}

小结

在路由处理函数中,我们可以获取请求参数,处理业务请求,并响应客户端的请求,具体要怎么做呢?我们在下一篇文章中再来讲解!