为何Go语言中HTTP DELETE请求的r.Form与r.PostForm始终为空?
问题原因与解决方案
你遇到的问题核心在于Go的r.Form/r.PostForm只处理表单编码的请求体,而你的DELETE请求发送的是JSON格式数据,具体细节如下:
r.Form和r.PostForm是为application/x-www-form-urlencoded或multipart/form-data这类表单编码请求设计的,Go会自动解析这类请求体并填充到这两个映射中,但JSON格式(application/json)不在自动解析的范围内。- 即使是表单编码的DELETE请求,Go默认也不会自动调用
ParseForm()来解析请求体,需要手动触发——但这对你的JSON请求场景完全不适用。
正确的解决方案:解析JSON请求体
你需要手动解析请求体中的JSON数据,步骤如下:
1. 定义与JSON结构匹配的结构体
先创建一个结构体来映射你的JSON请求字段:
type DeleteProductRequest struct { CustomerDate string `json:"CustomerDate"` CustomerDateTime string `json:"CustomerDateTime"` UserId int `json:"UserId"` }
2. 在处理器中解析JSON并处理请求
修改你的DeleteProduct方法,解析JSON请求体,同时注意避免SQL注入风险:
import ( "encoding/json" "log" "net/http" ) func DeleteProduct(w http.ResponseWriter, r *http.Request) { // 首先验证请求的Content-Type是JSON if r.Header.Get("Content-Type") != "application/json" { http.Error(w, "请使用application/json格式发送请求", http.StatusBadRequest) return } // 解析JSON请求体到结构体 var req DeleteProductRequest decoder := json.NewDecoder(r.Body) if err := decoder.Decode(&req); err != nil { http.Error(w, "JSON解析失败:"+err.Error(), http.StatusBadRequest) return } defer r.Body.Close() // 务必关闭请求体,避免资源泄漏 // 使用参数化查询执行删除操作(绝对禁止直接拼接SQL!防止SQL注入) result, err := db.Exec("DELETE FROM products WHERE UserId = ?", req.UserId) if err != nil { log.Printf("删除产品失败:%v", err) http.Error(w, "服务器内部错误", http.StatusInternalServerError) return } // 可选:记录操作日志或返回操作结果 rowsAffected, _ := result.RowsAffected() log.Printf("成功删除%d条记录,请求数据:%+v", rowsAffected, req) w.WriteHeader(http.StatusOK) w.Write([]byte("删除成功")) }
重要提醒
- SQL注入防护:你原来的代码直接将
r.FormValue("Id")拼接到SQL语句中,这是极高风险的操作,攻击者可以通过构造恶意参数篡改你的数据库。始终使用参数化查询(?占位符)来传递变量。 - 请求体关闭:无论是否解析成功,都要调用
r.Body.Close(),否则会导致Go的HTTP连接池资源泄漏。 - REST规范:DELETE请求携带JSON体是符合REST规范的,比表单编码更适合传递复杂数据。
内容的提问来源于stack exchange,提问作者Johannes Gnadlinger
相关产品推荐
相关产品推荐

