4. 路由与路径参数
任务说明
实现一个基于 net/http 标准库的 HTTP 服务,提供带路径参数的 RESTful 端点 /users/{id}。当客户端请求该端点时,服务端从 URL 路径中提取用户 ID,并返回包含该 ID 的 JSON 响应。同时提供 /users 端点用于创建用户,以构成完整的最小闭环。
实现方案
Go 1.22+ 的 net/http.ServeMux 原生支持路径参数(使用 {id} 语法),无需引入第三方库。通过 r.PathValue("id") 获取路径参数值。服务监听 :8080 端口,所有请求处理逻辑集中在 main.go 中。
代码实现
package main
import (
"encoding/json"
"log"
"net/http"
"strings"
)
// user 表示用户数据结构
type user struct {
ID string `json:"id"`
Name string `json:"name"`
}
// 内存数据存储,模拟数据库
var users = map[string]user{
"1": {ID: "1", Name: "Alice"},
"2": {ID: "2", Name: "Bob"},
}
func main() {
mux := http.NewServeMux()
// 路径参数端点:GET /users/{id}
mux.HandleFunc("GET /users/{id}", getUser)
// 创建用户:POST /users
mux.HandleFunc("POST /users", createUser)
// 健康检查
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
log.Println("Server listening on :8080")
if err := http.ListenAndServe(":8080", mux); err != nil {
log.Fatal(err)
}
}
// getUser 处理 GET /users/{id} 请求
func getUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id") // 获取路径参数
u, exists := users[id]
if !exists {
http.Error(w, `{"error":"user not found"}`, http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(u)
}
// createUser 处理 POST /users 请求
func createUser(w http.ResponseWriter, r *http.Request) {
var newUser user
if err := json.NewDecoder(r.Body).Decode(&newUser); err != nil {
http.Error(w, `{"error":"invalid request body"}`, http.StatusBadRequest)
return
}
// 简单校验:ID 不能为空且不能重复
newUser.ID = strings.TrimSpace(newUser.ID)
if newUser.ID == "" {
http.Error(w, `{"error":"id is required"}`, http.StatusBadRequest)
return
}
if _, exists := users[newUser.ID]; exists {
http.Error(w, `{"error":"user already exists"}`, http.StatusConflict)
return
}
users[newUser.ID] = newUser
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(newUser)
}
运行与验证
运行服务:
go run main.go
验证路径参数端点:
# 请求存在的用户
curl -i http://localhost:8080/users/1
# 预期响应(HTTP/1.1 200 OK)
# {"id":"1","name":"Alice"}
# 请求不存在的用户
curl -i http://localhost:8080/users/999
# 预期响应(HTTP/1.1 404 Not Found)
# {"error":"user not found"}
验证创建用户后再次通过路径参数访问:
# 创建新用户
curl -i -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"id":"3","name":"Charlie"}'
# 预期响应(HTTP/1.1 201 Created)
# {"id":"3","name":"Charlie"}
# 通过路径参数获取刚创建的用户
curl -i http://localhost:8080/users/3
# 预期响应(HTTP/1.1 200 OK)
# {"id":"3","name":"Charlie"}
判定标准
- 路径参数提取正确:请求
/users/1返回 ID 为 "1" 的用户数据,而非返回所有用户或固定数据。 - 动态路由生效:请求
/users/2返回 Bob 的数据,证明同一路由模式可匹配不同 ID 值。 - 错误处理有效:请求不存在的 ID(如
/users/999)返回 404 状态码和 JSON 错误信息。 - 数据一致性:通过
POST /users创建的新用户,可立即通过GET /users/{id}访问到,证明路径参数与数据存储联动正常。