最简Go Web服务需两行核心代码:http.HandleFunc注册路由,http.ListenAndServe启动监听;前者阻塞执行,后者须置于main末尾或协程中,且表单解析需显式调用r.ParseForm()。

最简可用的 Go Web 服务,两行核心代码就能跑起来:注册路由用 http.HandleFunc,启动监听用 http.ListenAndServe。但直接照抄示例常因端口占用、漏解析表单、忽略错误返回而失败。
为什么 http.ListenAndServe 会卡住程序不往下执行
http.ListenAndServe 是阻塞调用,它会一直占用当前 goroutine 直到服务退出或发生致命错误。这意味着函数之后的代码永远不会运行——不是 bug,是设计如此。
- 常见误写:
http.ListenAndServe(":8080", nil)后面还跟了日志打印或数据库初始化,结果完全不执行 - 正确做法:要么把它放在
main()最后一行;要么用go http.ListenAndServe(...)起新 goroutine(但要注意主 goroutine 退出会导致整个进程退出) - 生产环境更推荐用
http.Server结构体 +Shutdown,便于超时控制和优雅关闭
GET 和 POST 参数读不到?大概率没调 r.ParseForm()
Go 不自动解析表单或 query 字符串。漏掉这步,r.FormValue("key") 永远返回空字符串,且不报错,极难定位。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
-
r.URL.Query().Get("id")可安全读 URL 查询参数,无需提前解析 -
r.FormValue("name")能同时读 GET query 和 POST 表单字段,但必须先调r.ParseForm() - 上传文件需用
r.ParseMultipartForm(32 ,括号里是内存限制(如 32MB),否则会 panic - 对 JSON 请求体,别用
FormValue,应直接读r.Body并用json.Decode
路由注册后访问 404?检查路径结尾斜杠和重复注册
http.ServeMux(包括默认的 http.DefaultServeMux)只做前缀匹配,且对路径结尾斜杠敏感。注册逻辑不支持通配符或路径参数(如 /user/:id)。
立即学习“go语言免费学习笔记(深入)”;
-
mux.HandleFunc("/api", ...)不会匹配/api/users;要匹配子路径,得写/api/(注意末尾斜杠) - 重复注册同一路径(如两次
http.HandleFunc("/health", ...))会 panic,错误信息是http: multiple registrations for /health - 想避免全局状态污染或方便测试,应显式创建
mux := http.NewServeMux(),而非依赖默认 multiplexer - 需要路径参数或正则路由?直接换
gin或echo,原生net/http不提供
最容易被忽略的是:端口被占时 http.ListenAndServe 返回非 nil 错误,但很多人只写 http.ListenAndServe(":8080", nil) 而不检查 err,导致服务看似启动实则失败。加一行 if err != nil { log.Fatal(err) } 能省掉大半排查时间。

















