当路由数量多了之后,全部写在一起会很乱。路由分组可以把相关的路由组织在一起,还能共享中间件和前缀。
使用 Group() 创建路由组:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
api := r.Group("/api")
{
api.GET("/users", getUsers)
api.GET("/posts", getPosts)
}
r.Run(":8080")
}
func getUsers(c *gin.Context) {
c.JSON(200, gin.H{"users": []string{"Alice", "Bob"}})
}
func getPosts(c *gin.Context) {
c.JSON(200, gin.H{"posts": []string{"Post 1", "Post 2"}})
}
访问 /api/users 和 /api/posts 会分别调用对应的处理函数。
分组可以嵌套:
r := gin.Default()
v1 := r.Group("/api/v1")
{
users := v1.Group("/users")
{
users.GET("", listUsers)
users.GET("/:id", getUser)
users.POST("", createUser)
}
posts := v1.Group("/posts")
{
posts.GET("", listPosts)
posts.GET("/:id", getPost)
}
}
这样路由结构更清晰:
/api/v1/users/api/v1/users/:id/api/v1/posts/api/v1/posts/:id分组可以有自己的中间件,组内所有路由都会应用:
r := gin.Default()
api := r.Group("/api")
api.Use(func(c *gin.Context) {
c.Set("api", true)
c.Next()
})
api.GET("/data", func(c *gin.Context) {
isAPI := c.GetBool("api")
c.JSON(200, gin.H{"api": isAPI})
})
api := r.Group("/api")
api.Use(
authMiddleware(),
loggingMiddleware(),
rateLimitMiddleware(),
)
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
setupRoutes(r)
r.Run(":8080")
}
func setupRoutes(r *gin.Engine) {
v1 := r.Group("/api/v1")
v1.Use(apiVersionMiddleware())
setupUserRoutes(v1)
setupPostRoutes(v1)
}
func setupUserRoutes(rg *gin.RouterGroup) {
users := rg.Group("/users")
users.Use(userAuthMiddleware())
users.GET("", listUsers)
users.GET("/:id", getUser)
users.POST("", createUser)
users.PUT("/:id", updateUser)
users.DELETE("/:id", deleteUser)
}
func setupPostRoutes(rg *gin.RouterGroup) {
posts := rg.Group("/posts")
posts.Use(postAuthMiddleware())
posts.GET("", listPosts)
posts.GET("/:id", getPost)
posts.POST("", createPost)
posts.PUT("/:id", updatePost)
posts.DELETE("/:id", deletePost)
}
func apiVersionMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("version", "v1")
c.Next()
}
}
func userAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "需要认证"})
c.Abort()
return
}
c.Next()
}
}
func postAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
}
}
func listUsers(c *gin.Context) {
c.JSON(200, gin.H{"users": []string{}})
}
func getUser(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id})
}
func createUser(c *gin.Context) {
c.JSON(201, gin.H{"message": "用户创建成功"})
}
func updateUser(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id, "message": "更新成功"})
}
func deleteUser(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id, "message": "删除成功"})
}
func listPosts(c *gin.Context) {
c.JSON(200, gin.H{"posts": []string{}})
}
func getPost(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id})
}
func createPost(c *gin.Context) {
c.JSON(201, gin.H{"message": "文章创建成功"})
}
func updatePost(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id, "message": "更新成功"})
}
func deletePost(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{"id": id, "message": "删除成功"})
}
路由分组带来的优势:
这一章学习了: