
本文介绍如何在基于 go-json-rest 的 rest api 中正确提取和使用 url 查询参数(如 `?hello=world`),并通过 `r.request.formvalue` 或 `r.request.url.query()` 安全读取键值对。
在使用 go-json-rest 构建 RESTful 服务时,路径参数(如 /reminders/:id)可通过 r.PathParams 获取,但查询参数(即 URL 中 ? 后的部分,例如 localhost:8080/reminders?hello=world&limit=10)需通过底层 *http.Request 对象访问——因为 go-json-rest 是对标准库 net/http 的轻量封装,其 rest.Request 结构体中嵌套了原始的 *http.Request,可通过 r.Request 字段直接调用。
✅ 推荐方式:使用 r.Request.URL.Query()
这是最直观、语义最清晰的方式,专用于解析查询字符串:
func (i *Impl) GetAllReminders(w rest.ResponseWriter, r *rest.Request) {
// 解析查询参数为 url.Values(map[string][]string)
query := r.Request.URL.Query()
// 获取单个参数值(返回第一个匹配项,若不存在则为空字符串)
hello := query.Get("hello") // "world"
limitStr := query.Get("limit") // "10"
// 获取所有同名参数值(适用于多值场景,如 ?tag=a&tag=b)
tags := query["tag"] // []string{"a", "b"}
// 示例:转换 limit 并用于分页
var limit int = 20
if limitStr != "" {
if n, err := strconv.Atoi(limitStr); err == nil {
limit = n
}
}
reminders := []Reminder{}
i.DB.Limit(limit).Find(&reminders)
w.WriteJson(&reminders)
}? 注意:query.Get(key) 是安全的,即使 key 不存在也返回空字符串;而 query[key] 返回 []string,需手动判空。
⚠️ 补充说明:r.Request.Form 与 r.Request.FormValue
- r.Request.Form 在首次访问时会自动调用 ParseForm(),同时解析 GET 查询参数和 POST 表单数据(含 application/x-www-form-urlencoded)。但在纯 GET 请求中,它等价于 URL.Query()。
- r.Request.FormValue("key") 是便捷方法,内部调用 ParseForm() 后返回 Form[key] 的首个值,行为类似 URL.Query().Get(key),但隐式触发解析——对于只含查询参数的 GET 请求,推荐优先使用 URL.Query(),避免不必要的解析开销。
? 不要这样做
// ❌ 错误:r.PathParams 只处理路由路径中的占位符(如 /reminders/:id),不包含查询参数 _ = r.PathParams["hello"] // 始终为 nil 或 panic // ❌ 避免手动解析 r.Request.URL.RawQuery —— 重复造轮子且易出错
✅ 最佳实践总结
- ✅ 使用 r.Request.URL.Query() 获取查询参数,语义明确、性能高效;
- ✅ 用 query.Get("key") 读取单值,用 query["key"] 获取全部值;
- ✅ 对数值型参数(如 limit, offset)务必做类型转换与错误处理;
- ✅ 若接口需同时支持 GET 查询参数和 POST 表单提交,再考虑 FormValue;
- ✅ 所有外部输入(包括查询参数)都应校验合法性,防止注入或越界(如 limit 应设上限)。
通过以上方式,你就能在 go-json-rest 中稳健、清晰地处理任意复杂度的查询参数逻辑。










