公众号:程序员读书,欢迎关注
在上一篇文章中,我们已经学会了如何使用Gin
框架启动一个Web
服务器,但如果要接收并处理HTTP
请求,则还需要设置路由。
什么是路由
在Web
开发中,路由用于指定一个Web
接口被请求的路径(path
)以及接收请求的方法(如POST
,GET
等)。
路由配置
在Gin
框架中,我们可以按照HTTP
请求方法进行路由分配,对于有共同前缀的路由还可以使用路由分组来简化路由的设置,甚至可以使用通配符匹配某一模式的路由。
简单路由
创建gin.Engne
对象后,可以调用gin.Engine
对象的GET
等方法分配路由处理HTTP
请求:
go
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()
}
从上面的示例可以看到,处理对应路由的函数签名为:
go
func(ctx *gin.Context) {}
实际,在设置路由时,也可以同时添加多个处理函数:
go
engine.GET("/myGet", func(ctx *gin.Context) {
//中间件
ctx.Next()
},func(ctx *gin.Context){
//业务处理逻辑
})
如果一个路由添加了多个处理函数,本质上是添加中间件,因此前面的处理函数必须Next()
方法才会执行下一个处理函数。
除了以上与HTTP
请求方法一一对应的几外方法,还可以通过下面三个方法进行路由设置:
scss
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()
方法。
go
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()
}
路由分组
如果多个路由有共同的前缀,一个个设置可能会比较麻烦,如:
javascript
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
框架支持对路由进行分组,同一个分组的路由拥有共同的路由前缀,因此上面的路由设置可以采用路由分组的形式进行划分:
go
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
路由除了是普通字符串外,还可以是通配符:
和*
:
go
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) {})
}
通配符使用限制
通配符后面必须有一个名称,因此下面的用法是错误的:
bash
/user/*
/order/:
正确的用法是通配符后面必须有一个名称:
bash
/user/*name
/order/:id
同一级路由不能有两个路由,因此下面的用法是错误:
bash
/user/::id
/user/**name
通配符*
只能放在最后一级路由:
bash
# 错误用法
/dashbaord/*/goods/
# 正确
/dashboard/*
设置了*
通配符之后,如果在同一级路由设置其他的路由,Gin
框架会认为路由重复:
bash
# 由于有*通配符,因此同一级不能再设置路由
/dashobard/edit
/dashboard/*
对于:
通配符,同一级路由也只能设置一个:
bash
# 错误用法,即使名称不同,也只能设置一个
/user/:id
/user/:name
注意:路由重复是在同一种HTTP
请求方法内才有的限制,在上面的例子中,如果/user/:id
用于GET
请求,而/user/:name
用于POST
请求,则不会有这样的限制:
go
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) {})
}
小结
在路由处理函数中,我们可以获取请求参数,处理业务请求,并响应客户端的请求,具体要怎么做呢?我们在下一篇文章中再来讲解!