Go标准库net/http自带goroutine级并发,每个请求自动运行在独立goroutine中;关键在于避免阻塞逻辑、保护共享状态、设置Read/Write/Idle三项超时。

直接用 net/http + http.Server 就能跑出高并发能力,不需要框架或额外模块——Go 标准库本身已内置 goroutine 级别并发,关键在于别写阻塞逻辑、别共享无保护状态、别漏设超时。
为什么不用框架也能高并发
Go 的 http.Server 在 Accept 连接后,每个请求自动起一个新 goroutine 执行 handler,这是语言层原生支持的,并非某框架“实现”的特性。你写的 func(w http.ResponseWriter, r *http.Request) 本身就是并发执行单元。
- 只要 handler 内不调用
time.Sleep、不串行等待多个数据库查询、不共用未加锁的全局 map,就天然并行 - goroutine 开销极小(初始栈仅 2KB),万级并发常见且稳定
- 第三方路由器如
chi或gorilla/mux只是增强路由能力,不提升并发上限;反而可能因中间件链增加微小延迟
必须设置的三个超时参数
没设超时的 http.Server 在网络抖动、客户端断连不通知时会持续占用 goroutine 和连接,最终耗尽资源。以下三项缺一不可:
-
ReadTimeout:从连接建立到读完请求头+体的最大时间,防止慢速攻击(如 Slowloris) -
WriteTimeout:从开始写响应到完成写入的最长时间,避免大文件传输卡住 -
IdleTimeout:HTTP/1.1 keep-alive 连接空闲多久后关闭,防止僵尸连接堆积
示例:
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
server := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 15 * time.Second,
}
log.Fatal(server.ListenAndServe())避免踩坑:全局 http.HandleFunc 不能用于多服务实例
如果你要启动多个 http.Server(比如一个 API 端口 + 一个健康检查端口),千万别用 http.HandleFunc 注册路由——它会往全局 http.DefaultServeMux 写,导致冲突或覆盖。
- 正确做法:每个服务器用独立
http.NewServeMux(),然后赋给Server.Handler - 注册路由时调用
mux.HandleFunc(...),而非http.HandleFunc(...) - 第三方路由器(如
chi)也需显式传给Server.Handler,不要混用全局注册
错误示范:http.HandleFunc("/health", healthHandler) → 多个 server 共享同一 mux,第二 server 启动时 panic
性能敏感点:静态文件和 gzip 压缩别手写
自己拼接 os.Open + io.Copy 返回静态文件,既易出错又无法利用内核 sendfile 优化;不压缩文本响应则浪费带宽。
- 静态文件直接用
http.FileServer(http.Dir("./static")),它内部已做缓存头、ETag、范围请求支持 - gzip 压缩用
golang.org/x/net/http2/h2c(HTTP/2)或中间件如github.com/gorilla/handlers.CompressHandler,别在 handler 里手动压缩 - 注意:压缩中间件必须放在路由之前,否则无法捕获所有响应流
真正影响并发吞吐的,从来不是“用了什么框架”,而是连接管理是否健壮、I/O 是否异步、共享状态是否受控——这些都发生在你写的 handler 里,不在模块选择上。

















