用http.listenandserve启动服务时须检查错误并避免nil handler;统一使用自定义servemux而非混用全局路由;注意body只能读一次,依content-type分流解析;生产环境禁用defaultservemux以防信息泄露。

用 http.ListenAndServe 启动最简服务,但别直接裸奔
Go 写 HTTP 服务器,第一行代码几乎必是 http.ListenAndServe。它默认用 http.DefaultServeMux 路由,启动后阻塞等待请求。但直接这么写容易出问题:http.ListenAndServe 返回错误时不会自动 panic,如果端口被占或 TLS 配置错,程序静默退出,连日志都不打。
- 务必检查返回值:写成
log.Fatal(http.ListenAndServe(":8080", nil)),而不是丢掉错误 - 不要传
nil当 handler —— 它会 fallback 到全局DefaultServeMux,而这个 mux 是包级变量,多处注册路由会互相污染 - 开发时加超时控制更安全:用
http.Server结构体显式构造,设置ReadTimeout、WriteTimeout
路由注册别混用 http.HandleFunc 和自定义 http.ServeMux
http.HandleFunc 看似方便,其实是往全局 DefaultServeMux 注册;而自己 new 出来的 http.ServeMux 是独立实例。混用会导致路由“看不见”——比如你写了 mux := http.NewServeMux(),却调 http.HandleFunc("/api", ...),那这个 handler 实际挂在全局 mux 上,你的 mux 根本没收到它。
- 统一风格:要么全用
http.HandleFunc+nilhandler(仅限极简原型) - 要么全用自定义
http.ServeMux实例,再传给http.Server{Handler: mux} - 注意
http.ServeMux不支持通配符或正则,/users/和/users是两个不同路径,末尾斜杠不自动补全
处理 POST 表单或 JSON 时,r.ParseForm 和 json.Decode 不能乱序
HTTP 请求的 body 只能读一次。如果先调 r.ParseForm(),它内部会调 r.Body 读取并解析为 map[string][]string,之后再想用 json.NewDecoder(r.Body).Decode(...) 就会得到空数据或 io.EOF 错误。
- 表单提交(
application/x-www-form-urlencoded或multipart/form-data):只用r.ParseForm(),然后从r.FormValue("key")取值 - JSON 提交(
application/json):跳过ParseForm,直接json.NewDecoder(r.Body).Decode(&v) - 不确定类型?先用
r.Header.Get("Content-Type")判断,再分流处理;别试图反复读r.Body
生产环境必须禁用 http.DefaultServeMux,并关闭调试信息
用 nil 当 handler 会让 Go 自动启用 DefaultServeMux,它自带两个隐藏行为:一是把未注册路径重定向到带斜杠的版本(比如 GET /api → 301 到 /api/),二是当访问根路径且无 handler 时,会列出当前注册的所有路由——这在生产环境等于暴露接口结构。
- 显式传入自定义
http.ServeMux或http.Handler,彻底绕过DefaultServeMux - 关掉文件服务器自动 fallback:默认 mux 在找不到路由时会尝试把请求当作静态文件服务,这可能泄露
./下任意可读文件 - 错误响应别打堆栈:用
http.Error(w, "bad request", http.StatusBadRequest),而不是panic或打印debug.PrintStack()
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











