路由基础 #

一、路由概述 #

1.1 什么是路由 #

路由是将HTTP请求映射到处理函数的机制。Fiber提供了强大而灵活的路由系统。

text
HTTP请求 → 路由匹配 → 处理函数 → 响应

1.2 路由组成 #

一个完整的路由由以下部分组成:

go
app.Get("/users/:id", handler)

// 组成部分:
// - Get: HTTP方法
// - /users/:id: 路由路径
// - handler: 处理函数

二、基本路由 #

2.1 定义路由 #

go
package main

import "github.com/gofiber/fiber/v2"

func main() {
    app := fiber.New()
    
    // GET请求
    app.Get("/hello", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World!")
    })
    
    // POST请求
    app.Post("/users", func(c *fiber.Ctx) error {
        return c.SendString("Create User")
    })
    
    // PUT请求
    app.Put("/users/:id", func(c *fiber.Ctx) error {
        return c.SendString("Update User")
    })
    
    // DELETE请求
    app.Delete("/users/:id", func(c *fiber.Ctx) error {
        return c.SendString("Delete User")
    })
    
    // PATCH请求
    app.Patch("/users/:id", func(c *fiber.Ctx) error {
        return c.SendString("Patch User")
    })
    
    // HEAD请求
    app.Head("/info", func(c *fiber.Ctx) error {
        return c.SendString("Head Request")
    })
    
    // OPTIONS请求
    app.Options("/options", func(c *fiber.Ctx) error {
        return c.SendString("Options Request")
    })
    
    app.Listen(":3000")
}

2.2 匹配所有方法 #

go
// 匹配所有HTTP方法
app.All("/api", func(c *fiber.Ctx) error {
    return c.SendString("All methods")
})

// 使用Use匹配所有方法(作为中间件)
app.Use("/middleware", func(c *fiber.Ctx) error {
    return c.Next()
})

2.3 多个处理函数 #

go
// 多个处理函数链式调用
app.Get("/chain", 
    func(c *fiber.Ctx) error {
        c.Set("X-Custom", "value")
        return c.Next()
    },
    func(c *fiber.Ctx) error {
        return c.SendString("Chain handlers")
    },
)

三、路由参数 #

3.1 路径参数 #

go
// 必需参数
app.Get("/users/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    return c.SendString("User ID: " + id)
})

// 可选参数
app.Get("/users/:id?", func(c *fiber.Ctx) error {
    id := c.Params("id", "default")
    return c.SendString("User ID: " + id)
})

// 多个参数
app.Get("/users/:userId/posts/:postId", func(c *fiber.Ctx) error {
    userId := c.Params("userId")
    postId := c.Params("postId")
    return c.SendString("User: " + userId + ", Post: " + postId)
})

// 整数参数
app.Get("/page/:num", func(c *fiber.Ctx) error {
    num := c.ParamsInt("num", 1)
    return c.SendString("Page: " + strconv.Itoa(num))
})

3.2 通配符参数 #

go
// 单个通配符
app.Get("/files/*", func(c *fiber.Ctx) error {
    path := c.Params("*")
    return c.SendString("File path: " + path)
})

// 命名通配符
app.Get("/files/*filepath", func(c *fiber.Ctx) error {
    filepath := c.Params("filepath")
    return c.SendString("File: " + filepath)
})

// 组合使用
app.Get("/api/:version/*path", func(c *fiber.Ctx) error {
    version := c.Params("version")
    path := c.Params("path")
    return c.SendString("Version: " + version + ", Path: " + path)
})

3.3 查询参数 #

go
app.Get("/search", func(c *fiber.Ctx) error {
    // 获取单个参数
    q := c.Query("q")
    
    // 带默认值
    page := c.Query("page", "1")
    
    // 获取所有参数
    queries := c.Queries()
    
    return c.JSON(fiber.Map{
        "query":   q,
        "page":    page,
        "queries": queries,
    })
})

四、路由配置 #

4.1 严格路由 #

go
// 默认情况下,/foo 和 /foo/ 被视为相同
app := fiber.New(fiber.Config{
    StrictRouting: true, // 区分 /foo 和 /foo/
})

app.Get("/foo", func(c *fiber.Ctx) error {
    return c.SendString("foo")
})

app.Get("/foo/", func(c *fiber.Ctx) error {
    return c.SendString("foo/")
})

4.2 大小写敏感 #

go
app := fiber.New(fiber.Config{
    CaseSensitive: true, // 区分大小写
})

app.Get("/Foo", func(c *fiber.Ctx) error {
    return c.SendString("Foo")
})

// /Foo 匹配
// /foo 不匹配

4.3 路由配置选项 #

go
app := fiber.New(fiber.Config{
    // 严格路由
    StrictRouting: false,
    
    // 大小写敏感
    CaseSensitive: false,
    
    // 不可变
    Immutable: false,
    
    // 严格模式(解析时严格检查)
    UnescapePath: true,
    
    // 启用路由追踪
    EnableTrustedProxyCheck: true,
})

五、路由分组 #

5.1 基本分组 #

go
func main() {
    app := fiber.New()
    
    // API v1分组
    v1 := app.Group("/api/v1")
    v1.Get("/users", getUsers)
    v1.Get("/users/:id", getUser)
    v1.Post("/users", createUser)
    
    // API v2分组
    v2 := app.Group("/api/v2")
    v2.Get("/users", getUsersV2)
    v2.Get("/users/:id", getUserV2)
    
    app.Listen(":3000")
}

5.2 嵌套分组 #

go
func main() {
    app := fiber.New()
    
    api := app.Group("/api")
    
    // 用户模块
    users := api.Group("/users")
    users.Get("/", listUsers)
    users.Get("/:id", getUser)
    users.Post("/", createUser)
    
    // 用户下的文章
    posts := users.Group("/:userId/posts")
    posts.Get("/", listPosts)
    posts.Get("/:postId", getPost)
    
    // 最终路由:
    // GET  /api/users
    // GET  /api/users/:id
    // POST /api/users
    // GET  /api/users/:userId/posts
    // GET  /api/users/:userId/posts/:postId
    
    app.Listen(":3000")
}

5.3 分组中间件 #

go
func main() {
    app := fiber.New()
    
    // API分组带中间件
    api := app.Group("/api", func(c *fiber.Ctx) error {
        c.Set("X-API-Version", "1.0")
        return c.Next()
    })
    
    // 认证分组
    auth := api.Group("/auth", authMiddleware)
    auth.Get("/profile", getProfile)
    auth.Get("/settings", getSettings)
    
    // 公开路由
    api.Get("/public", func(c *fiber.Ctx) error {
        return c.SendString("Public API")
    })
    
    app.Listen(":3000")
}

func authMiddleware(c *fiber.Ctx) error {
    token := c.Get("Authorization")
    if token == "" {
        return c.Status(401).JSON(fiber.Map{
            "error": "Unauthorized",
        })
    }
    return c.Next()
}

六、路由命名 #

6.1 命名路由 #

go
func main() {
    app := fiber.New()
    
    // 命名路由
    app.Get("/users/:id", func(c *fiber.Ctx) error {
        return c.SendString("User")
    }).Name("user.show")
    
    app.Post("/users", func(c *fiber.Ctx) error {
        return c.SendString("Create User")
    }).Name("user.store")
    
    // 获取路由名称
    app.Get("/routes", func(c *fiber.Ctx) error {
        routes := app.GetRoutes()
        var names []string
        for _, route := range routes {
            names = append(names, route.Name)
        }
        return c.JSON(names)
    })
    
    app.Listen(":3000")
}

6.2 生成URL #

go
func main() {
    app := fiber.New()
    
    app.Get("/users/:id", func(c *fiber.Ctx) error {
        return c.SendString("User")
    }).Name("user.show")
    
    app.Get("/test", func(c *fiber.Ctx) error {
        // 生成URL
        url, err := app.GetRouteURL("user.show", fiber.Map{
            "id": 123,
        })
        if err != nil {
            return err
        }
        return c.SendString("URL: " + url)
    })
    
    app.Listen(":3000")
}

七、路由列表 #

7.1 获取所有路由 #

go
func main() {
    app := fiber.New()
    
    app.Get("/", handler)
    app.Get("/users", handler)
    app.Post("/users", handler)
    
    // 打印所有路由
    routes := app.GetRoutes()
    for _, route := range routes {
        fmt.Printf("%s %s\n", route.Method, route.Path)
    }
    
    app.Listen(":3000")
}

7.2 路由信息 #

go
type Route struct {
    Method  string   // HTTP方法
    Name    string   // 路由名称
    Path    string   // 路由路径
    Params  []string // 参数列表
    Handlers []Handler // 处理函数
}

八、路由匹配规则 #

8.1 匹配优先级 #

Fiber按照以下优先级匹配路由:

text
1. 静态路由(/users/list)
2. 动态路由(/users/:id)
3. 通配符路由(/users/*)
go
app.Get("/users/list", func(c *fiber.Ctx) error {
    return c.SendString("Static: list")
})

app.Get("/users/:id", func(c *fiber.Ctx) error {
    return c.SendString("Dynamic: " + c.Params("id"))
})

app.Get("/users/*", func(c *fiber.Ctx) error {
    return c.SendString("Wildcard: " + c.Params("*"))
})

// /users/list  → "Static: list"
// /users/123   → "Dynamic: 123"
// /users/a/b/c → "Wildcard: a/b/c"

8.2 路由冲突 #

go
// 错误:参数名冲突
// app.Get("/users/:id", handler)
// app.Get("/users/:name", handler) // 会覆盖前面的路由

// 正确:使用不同的路径
app.Get("/users/id/:id", handler)
app.Get("/users/name/:name", handler)

九、实战示例 #

9.1 RESTful API路由 #

go
func main() {
    app := fiber.New()
    
    // 用户资源
    users := app.Group("/users")
    users.Get("/", listUsers)           // 列表
    users.Get("/:id", getUser)          // 详情
    users.Post("/", createUser)         // 创建
    users.Put("/:id", updateUser)       // 更新
    users.Delete("/:id", deleteUser)    // 删除
    
    // 文章资源
    posts := app.Group("/posts")
    posts.Get("/", listPosts)
    posts.Get("/:id", getPost)
    posts.Post("/", createPost)
    posts.Put("/:id", updatePost)
    posts.Delete("/:id", deletePost)
    
    // 评论资源(嵌套)
    posts.Get("/:postId/comments", listComments)
    posts.Post("/:postId/comments", createComment)
    
    app.Listen(":3000")
}

9.2 版本化API #

go
func main() {
    app := fiber.New()
    
    // v1版本
    v1 := app.Group("/v1")
    v1.Get("/users", getUsersV1)
    v1.Get("/posts", getPostsV1)
    
    // v2版本
    v2 := app.Group("/v2")
    v2.Get("/users", getUsersV2)
    v2.Get("/posts", getPostsV2)
    
    // 默认版本(指向最新)
    app.Get("/users", getUsersV2)
    
    app.Listen(":3000")
}

十、总结 #

10.1 核心要点 #

要点 说明
路由定义 app.Get()、app.Post()等方法
路径参数 :id 必需参数,:id? 可选参数
通配符 * 匹配任意路径
路由分组 app.Group() 组织路由
中间件 分组级别应用中间件

10.2 下一步 #

现在你已经掌握了路由基础,接下来让我们学习 路由参数,深入了解参数处理!

最后更新:2026-03-28