应检查 http.ListenAndServe 错误并用 log.Fatal(err),显式构造 http.Server 以配置超时、TLS等;注意 http.HandleFunc 与 http.Handle 类型差异;request.Body 只能读一次;务必设置 Read/Write/IdleTimeout 防连接泄漏。

用 http.ListenAndServe 启动最简服务,但别忽略错误处理
直接调用 http.ListenAndServe(":8080", nil) 能跑起来,但一旦端口被占或网络异常,程序会静默 panic 或直接退出。Go 的 HTTP 服务器本身不自动重试、不自动日志、不自动超时控制。
实操建议:
- 始终检查返回错误,至少加
log.Fatal(err),而不是忽略 - 用
http.Server结构体显式构造,便于后续配置 TLS、超时、连接池等 - 监听地址建议写成
":8080"而非"localhost:8080",后者会绑定到 IPv4 回环,可能无法从容器外访问
http.HandleFunc 和 http.Handle 的区别:函数 vs 接口,选错会导致路由失效
http.HandleFunc 注册的是函数(func(http.ResponseWriter, *http.Request)),而 http.Handle 要求传入实现了 http.Handler 接口的值(比如自定义 struct 或 http.ServeMux)。混用会导致编译失败或路由不生效。
常见错误现象:
立即学习“go语言免费学习笔记(深入)”;
- 误把函数字面量传给
http.Handle:编译报错cannot use func(...) (type func(...)) as type http.Handler - 用
http.HandleFunc注册了路径"/api",但实际请求是"/api/"(带尾斜杠)——默认ServeMux不自动重定向,需手动处理
推荐做法:初期用 http.HandleFunc 快速验证;中后期迁移到自定义 http.ServeMux 或第三方路由器(如 chi),便于分组和中间件管理。
如何安全地读取请求体?别在多个地方调用 r.Body
*http.Request.Body 是一个 io.ReadCloser,只能读一次。多次调用 io.ReadAll(r.Body) 或 json.NewDecoder(r.Body).Decode(...) 会导致后续读取返回空或 EOF。
Destoon B2B网站管理系统是一套完善的B2B(电子商务)行业门户解决方案。系统基于PHP+MySQL开发,采用B/S架构,模板与程序分离,源码开放。模型化的开发思路,可扩展或删除任何功能;创新的缓存技术与数据库设计,可负载千万级别数据容量及访问。 系统特性1、跨平台。支持Linux/Unix/Windows服务器,支持Apache/IIS/Zeus等2、跨浏览器。基于最新Web标准构建,在
使用场景与对策:
- 需要解析 JSON 又要记录原始 body:先用
io.ReadAll读一次,再用bytes.NewReader构造新 reader 供后续使用 - 中间件中做鉴权或日志:必须在 handler 执行前完成读取,并将数据存入
r.Context()或自定义 request wrapper - 上传文件时用
r.ParseMultipartForm,它内部已处理 body 复用逻辑,无需额外缓存
生产环境必须设置 ReadTimeout、WriteTimeout 和 IdleTimeout
默认情况下,Go 的 http.Server 没有超时限制。客户端断连、慢攻击、长轮询未关连接,都会导致 goroutine 和文件描述符持续累积,最终 OOM 或 too many open files。
关键参数含义:
-
ReadTimeout:从连接建立到读完 request header 的最大时间(不含 body) -
WriteTimeout:从 request header 解析完成到 response 写完的总耗时上限 -
IdleTimeout:keep-alive 连接空闲等待下一个 request 的最长时间(Go 1.8+ 推荐设为 30–60s)
示例配置:
srv := &http.Server{
Addr: ":8080",
Handler: myRouter,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
}注意:ReadTimeout 过短会影响大表单或上传;WriteTimeout 过短会中断正常业务逻辑,应按接口 SLA 设置,而非统一硬编码。
HTTP 服务器看似简单,真正难的是边界控制:连接生命周期、body 读取顺序、超时粒度、上下文传递。这些地方不显眼,但出问题时往往没有明确错误信息,只表现为延迟升高或连接泄漏。









