Fiber中取路径参数必须用c.Params("name"),且路由须显式声明如"/user/:id";未声明或写错格式(如"{id}"或":id/")均返回空字符串,不可混用c.QueryParam()。

怎么取路径参数(c.Params())
路径参数必须在路由定义里显式声明,比如 app.Get("/user/:id", handler),否则 c.Params("id") 永远返回空字符串。Fiber 不会自动从 URL 字符串里“猜”参数名,它只认路由模板中写死的占位符。
常见错误:写了 /user/123 请求,但路由注册的是 /user/{id} 或 /user/:id/ —— 这两种写法 Fiber 都不识别,直接 404。严格匹配模式(StrictRouting: true)下,/user/123 和 /user/123/ 是两条不同路由。
-
c.Params("id")返回的是内部字节切片引用,不能存到 map 或结构体字段里长期使用;高并发时 goroutine 中直接用它可能读到下一个请求的值 - 通配符
*要写成app.Get("/files/*", handler),取值用c.Params("*"),不是c.Params("star") - 别和
c.QueryParam("id")混用——前者来自路径,后者来自?id=123,完全无关
查询参数和表单数据怎么区分用(c.QueryParam() vs c.FormValue())
URL 查询参数(?page=2&sort=desc)必须用 c.QueryParam("page"),而表单提交(Content-Type: application/x-www-form-urlencoded)才用 c.FormValue("page")。两者底层来源不同,强行交叉调用一定为空。
注意 c.QueryParam() 比 c.Query() 更安全:对缺失 key 返回空字符串,不会 panic;而 c.FormValue() 对不存在的字段也返回空字符串,不用额外判空。
- 多值字段(如
<input name="tag" multiple>)用c.FormValues("tag"),返回[]string - 如果前端发的是 JSON(
Content-Type: application/json),别用c.FormValue(),得走c.BodyParser(&v) - 上传文件时,
c.FormFile("file")必须配合c.SaveFile(),不能用c.Body()手动读,否则破坏 multipart 解析状态
PUT/DELETE 请求体为什么总拿不到数据
浏览器原生 <form> 标签根本不支持 method="put",写上去会被忽略并退化为 GET。真 PUT/DELETE 必须由 fetch、axios 等 JS 发起,且请求体默认是 raw data(如 JSON),不是表单编码。
Fiber 不做方法重写,也不依赖 _method 隐藏字段——你发什么方法,它就收什么方法。所以如果 c.BodyParser() 失败,先看 Network 面板里 Request Method 到底是不是 PUT,而不是看前端代码里写的 method="put"。
- JSON 请求体:确保前端设了
Content-Type: application/json,后端用c.BodyParser(&v),结构体字段带json:"field"tag - FormData 请求体:Content-Type 是
multipart/form-data,Fiber 不自动解析,得手动调c.FormValue()或c.FormFile() - 别在中间件里提前调
c.Request().Body()或c.Request().RequestBody(),这会消耗流,导致后续c.Body()或绑定失败
为什么 c.Params() 和 c.Body() 的值有时“变掉了”
fiber.Ctx 是复用对象,内部缓冲区会在每次请求间重置。所以 c.Params("id") 返回的是指向该缓冲区的 string(底层是 []byte 引用),不是新分配的字符串。一旦下个请求进来,这块内存就被覆盖了。
同理,c.Body() 返回的是原始请求体字节切片的引用,也不是拷贝。如果你需要在 goroutine 里用、存进 map、或多次解析,必须手动拷贝:
- 安全取路径参数:
id := string(append([]byte(nil), c.Params("id")...))或id := c.Params("id") + "" - 安全读请求体:
body := append([]byte(nil), c.Body()...),之后用bytes.NewReader(body)重放 - 不要在中间件或 handler 里把
c传给异步函数,除非你明确复制了所有需要的数据


















