Contents

Go语言Web服务参数解析全解析

在构建Web服务时,解析客户端请求中的参数是核心功能之一。Go语言通过标准库 net/http 提供了简洁的接口来处理不同类型的请求参数。本文将通过示例代码,详细讲解如何解析URL参数表单数据请求体,并最终提供完整可运行的代码。


一、路由参数解析(URL参数)

在HTTP请求中,URL参数通常以 ?key1=value1&key2=value2 的形式附加在路径后。以下是如何在Go中解析这些参数:

关键代码解析

func paramParse(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() // 解析URL参数和表单数据
    fmt.Fprintf(w, "Method: %v\n", r.Method)
    fmt.Fprintf(w, "Form: %v\n", r.Form)      // 包含URL参数和POST表单数据
    fmt.Fprintf(w, "PostForm: %v\n", r.PostForm) // 仅POST表单数据
    fmt.Fprintf(w, "URL.RawQuery: %v\n", r.URL.RawQuery) // 原始查询字符串
}

核心知识点

  1. r.ParseForm()
    必须调用此方法才能解析请求中的参数,否则 r.Formr.PostForm 为空。

  2. r.Form vs r.PostForm

    • r.Form:包含URL查询参数和POST表单数据(混合)。
    • r.PostForm:仅包含POST表单数据(需Content-Type为 application/x-www-form-urlencoded)。
  3. r.URL.RawQuery
    直接获取原始查询字符串(如 name=John&age=30)。


二、请求体解析(表单和Body数据)

对于POST/PUT等请求,数据通常通过请求体传递。以下是解析请求体的方法:

关键代码解析

func bodyParse(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() // 解析表单数据
    fmt.Fprintf(w, "Method: %v\n", r.Method)
    fmt.Fprintf(w, "Form: %v\n", r.Form)      // 包含URL参数和POST表单数据
    fmt.Fprintf(w, "PostForm: %v\n", r.PostForm) // 仅POST表单数据
    fmt.Fprintf(w, "Body: %v\n", r.Body)      // 原始请求体(需手动读取)
}

核心知识点

  1. r.ParseForm() 的局限性
    仅能解析 application/x-www-form-urlencoded 类型的表单数据。若需处理JSON或其他格式,需直接读取 r.Body

    body, _ := io.ReadAll(r.Body)
    defer r.Body.Close()
    fmt.Fprintf(w, "Raw Body: %s\n", body)
  2. r.Body 的读取
    r.Body 是一个 io.ReadCloser 接口,需手动读取内容并关闭。

  3. 表单数据与JSON的区分

    • 表单数据:通过 r.Formr.PostForm 解析。
    • JSON数据:需读取 r.Body 后使用 json.Unmarshal 反序列化。

三、完整代码示例

将以下代码保存为 main.go,运行后可通过 curl 或浏览器测试不同接口:

package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func rootHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "API")
}

// 解析URL参数和表单数据
func paramParse(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	fmt.Fprintf(w, "Method: %v\n", r.Method)
	fmt.Fprintf(w, "Form: %v\n", r.Form)
	fmt.Fprintf(w, "PostForm: %v\n", r.PostForm)
	fmt.Fprintf(w, "URL.RawQuery: %v\n", r.URL.RawQuery)

	for k, v := range r.Form {
		fmt.Fprintf(w, "Form[%q] = %q\n", k, strings.Join(v, ""))
	}
}

// 解析请求体数据
func bodyParse(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	fmt.Fprintf(w, "Method: %v\n", r.Method)
	fmt.Fprintf(w, "Form: %v\n", r.Form)
	fmt.Fprintf(w, "PostForm: %v\n", r.PostForm)

	// 直接读取请求体(如JSON)
	body, _ := io.ReadAll(r.Body)
	defer r.Body.Close()
	fmt.Fprintf(w, "Raw Body: %s\n", body)
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/paramParse", paramParse)
	mux.HandleFunc("/bodyParse", bodyParse)
	http.ListenAndServe(":8080", mux)
}

四、运行与测试

1. 启动服务

go run main.go

2. 测试路由参数解析

curl "http://localhost:8080/paramParse?name=John&age=30"

输出示例:

Method: GET
Form: map[age:[30] name:[John]]
PostForm: map[]
URL.RawQuery: name=John&age=30
Form["age"] = "30"
Form["name"] = "John"

3. 测试请求体解析(表单)

curl -X POST -d "name=Jane&age=25" http://localhost:8080/bodyParse

输出示例:

Method: POST
Form: map[age:[25] name:[Jane]]
PostForm: map[age:[25] name:[Jane]]
Raw Body: name=Jane&age=25

4. 测试请求体解析(JSON)

curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob"}' http://localhost:8080/bodyParse

输出示例:

Method: POST
Form: map[]
PostForm: map[]
Raw Body: {"name":"Bob"}

五、总结

通过本文,我们学习了Go语言中处理Web请求参数的两种主要方式:

  1. URL参数解析:通过 r.Formr.URL.RawQuery 获取。
  2. 请求体解析:通过 r.PostForm 处理表单数据,或直接读取 r.Body 处理JSON等格式。

理解这些方法后,可以灵活应对不同场景的请求参数处理需求。完整的代码示例可直接运行测试,建议结合实践加深理解!