--- name: 集成请求参数获取方法 overview: 在 context.go 中为 Context 结构体添加五个请求参数获取方法:ReqData(统一获取)、ReqDataParams(URL参数)、ReqDataJson(JSON Body)、ReqDataForm(表单数据)、ReqFile(获取上传文件)。 todos: - id: add-imports content: 在 context.go 中添加 bytes、io、mime/multipart 包的导入 status: completed - id: impl-params content: 实现 ReqParam/ReqParams 方法(获取 URL 参数,返回 *Obj) status: in_progress dependencies: - add-imports - id: impl-form content: 实现 ReqForm/ReqForms 方法(获取表单数据,返回 *Obj) status: pending dependencies: - add-imports - id: impl-json content: 实现 ReqJson/ReqJsons 方法(获取 JSON Body,返回 *Obj) status: pending dependencies: - add-imports - id: impl-file content: 实现 ReqFile/ReqFiles 方法(获取上传文件) status: pending dependencies: - add-imports - id: impl-reqdata content: 实现 ReqData/ReqDatas 方法(统一获取,返回 *Obj) status: pending dependencies: - impl-params - impl-form - impl-json --- # 集成请求参数获取方法 ## 实现位置 在 [`context.go`](context.go) 中添加请求参数获取方法,**风格与 `Session("key")` 保持一致,返回 `*Obj` 支持链式调用**。 ## 新增方法 ### 1. ReqParam - 获取 URL 查询参数(返回 *Obj) ```go // 获取单个参数,支持链式调用 func (that *Context) ReqParam(key string) *Obj { // that.ReqParam("id").ToStr() // that.ReqParam("id").ToInt() } // 获取所有 URL 参数 func (that *Context) ReqParams() Map ``` ### 2. ReqForm - 获取表单数据(返回 *Obj) ```go // 获取单个表单字段 func (that *Context) ReqForm(key string) *Obj { // that.ReqForm("name").ToStr() } // 获取所有表单数据 func (that *Context) ReqForms() Map ``` ### 3. ReqJson - 获取 JSON Body(返回 *Obj) ```go // 获取 JSON 中的单个字段 func (that *Context) ReqJson(key string) *Obj { // that.ReqJson("data").ToMap() // that.ReqJson("count").ToInt() } // 获取完整 JSON Body func (that *Context) ReqJsons() Map ``` ### 4. ReqFile - 获取上传文件 ```go func (that *Context) ReqFile(name string) (multipart.File, *multipart.FileHeader, error) func (that *Context) ReqFiles(name string) ([]*multipart.FileHeader, error) ``` ### 5. ReqData - 统一获取参数(返回 *Obj) ```go // 统一获取(JSON > Form > URL),支持链式调用 func (that *Context) ReqData(key string) *Obj { // that.ReqData("id").ToStr() } // 获取所有合并后的参数 func (that *Context) ReqDatas() Map ``` ## 需要的导入 ```go import ( "bytes" "io" "mime/multipart" ) ``` ## 关键实现细节 1. **Body 只能读取一次的问题**:读取 Body 后需要用 `io.NopCloser(bytes.NewBuffer(body))` 恢复,以便后续代码(如其他中间件)还能再次读取 2. **废弃 API 替换**:使用 `io.ReadAll` 替代已废弃的 `ioutil.ReadAll` 3. **多值参数处理**:当同一参数有多个值时(如 `?id=1&id=2`),存储为 `Slice`;单值则直接存储字符串 ## 使用示例 ```go appIns.Run(Router{ "app": { "user": { "info": func(that *Context) { // 链式调用获取单个参数(类似 Session 风格) id := that.ReqData("id").ToInt() // 统一获取 name := that.ReqParam("name").ToStr() // URL 参数 age := that.ReqForm("age").ToCeilInt() // 表单参数 data := that.ReqJson("profile").ToMap() // JSON 字段 // 获取所有参数(返回 Map) allParams := that.ReqDatas() // 合并后的所有参数 urlParams := that.ReqParams() // 所有 URL 参数 formData := that.ReqForms() // 所有表单数据 jsonBody := that.ReqJsons() // 完整 JSON Body that.Display(0, Map{"id": id, "name": name}) }, "upload": func(that *Context) { // 获取单个上传文件 file, header, err := that.ReqFile("avatar") if err == nil { defer file.Close() // header.Filename - 文件名 // header.Size - 文件大小 } // 获取多个同名上传文件 files, err := that.ReqFiles("images") }, }, }, }) ``` ## 风格对比 | 旧方式(需要类型断言) | 新方式(链式调用) | |------------------------|-------------------| | `req["id"].(string) `| `that.ReqData("id").ToStr()` | | `ObjToInt(req["id"]) `| `that.ReqData("id").ToInt()` | | 需要手动处理 nil | `*Obj` 自动处理空值 |