在 URL 中,问号(?)是用于分隔路径和查询参数的特殊符号,其作用是将 URL 分为两部分:路径(Path)和查询参数(Query Parameters)。
二、? 的作用:分隔路径和查询参数
-
路径(Path)
位置:位于 ? 之前,用于标识服务器上的资源路径(如 /factorial)。
作用:告诉服务器需要访问的资源或接口(类似文件系统中的文件路径)。
示例:
在 http://localhost:8080/factorial?num=5 中,路径是 /factorial,表示访问服务器上的 /factorial 接口。
路径可以包含多级目录(如 /api/v1/user),由服务器的路由规则解析。 -
查询参数(Query Parameters)
位置:位于 ? 之后,格式为 键=值&键=值(如 num=5)。
作用:向服务器传递额外的参数(如用户输入的数字 5),用于处理请求逻辑。
特点:
多个参数用 & 分隔(如 ?name=Alice&age=20)。
参数名和值需进行 URL 编码(如空格用 %20 表示,特殊字符用 %XX 表示)。
不会修改资源路径,仅作为参数传递给服务器。 -
示例解析
以 http://localhost:8080/factorial?num=5 为例:
路径:/factorial,服务器通过路由规则匹配到处理该路径的函数(如 factorialHandler)。
查询参数:num=5,其中 num 是参数名,5 是参数值,表示请求计算 5 的阶乘。
三、服务器如何解析查询参数?
在 Go 的 HTTP 处理函数中,通过 r.URL.Query() 方法解析查询参数,返回一个 url.Values 类型(本质是键值对的映射)。
代码示例:
go
func factorialHandler(w http.ResponseWriter, r *http.Request) {
// 解析查询参数(获取所有参数的键值对)
queryParams := r.URL.Query()// 获取名为 "num" 的参数值(返回字符串)
numStr := queryParams.Get("num")// 将字符串转换为整数
num, err := strconv.Atoi(numStr)
if err != nil {
http.Error(w, "参数错误:num 必须是整数", http.StatusBadRequest)
return
}// 计算阶乘
result := 1
for i := 2; i <= num; i++ {
result *= i
}// 返回 JSON 结果
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(fmt.Sprintf({"num": %d, "factorial": %d}, num, result)))
}
关键步骤:
r.URL.Query():
解析 ? 后的查询参数,返回 url.Values(如 map[string][]string{"num": {"5"}})。
自动处理 URL 编码(如将 %20 转换为空格)。
queryParams.Get("num"):
根据参数名(如 num)获取对应的值,返回字符串(如 "5")。
若参数不存在,返回空字符串 ""。
四、为什么你的 URL 能访问?—— 路由注册的重要性
你提到的 URL http://localhost:8080/factorial?num=5 能访问的前提是:服务器已注册该路径的路由处理函数。
在 Go 的 net/http 包中,默认使用 http.ServeMux 作为路由 multiplexer(多路复用器),需要通过 http.HandleFunc(path, handler) 注册路径与处理函数的映射。
示例:
go
func main() {
// 注册路由:将 "/factorial" 路径绑定到 factorialHandler 函数
http.HandleFunc("/factorial", factorialHandler)// 启动服务器,监听 8080 端口
log.Println("服务器启动,监听 :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
如果未注册 /factorial 路由,访问该 URL 会返回 404 Not Found。
查询参数(如 ?num=5)不影响路由匹配,路由只根据路径(/factorial)匹配处理函数。
五、客户端 GET 请求的参数位置
在 HTTP 协议中,GET 请求的参数必须通过查询参数(即 ? 后的部分)传递,而不是请求体(Request Body)。
原因:
GET 请求的设计初衷是获取资源,参数应可见且幂等(多次请求结果相同)。
请求体在 GET 请求中是可选的,且大多数客户端(如浏览器)和服务器不会处理 GET 请求的请求体。
因此,在 URL 中通过 ?key=value 传递参数是 GET 请求的标准做法。
URL 中的 ? 是分隔路径和查询参数的关键符号:
路径:标识资源位置,用于服务器路由匹配。
查询参数:传递请求的具体参数,供服务器处理逻辑使用。
必须先注册路由路径(如 /factorial),URL 才能被正确处理。
如果需要处理更复杂的参数(如非文本数据),可以使用 POST 请求并通过请求体传递参数,但 GET 请求必须通过查询参数传递参数。
浙公网安备 33010602011771号