Go 1.8+ 默认启用 HTTP/2,前提是使用 http.ListenAndServeTLS 启动 HTTPS 服务;HTTP/2 不支持明文,Server Push 需通过 http.Pusher 实现,但 Go 1.23 已弃用该接口。

Go 1.8+ 默认支持 HTTP/2,无需额外配置
Go 从 1.8 版本起,只要使用 http.Server 启动 HTTPS 服务(即配置了 TLSConfig),底层会自动启用 HTTP/2 —— 不需要 import 额外包,也不用显式调用 http2.ConfigureServer。这是 Go 的默认行为,但很多人误以为要手动开启。
关键前提是:必须走 HTTPS。HTTP/2 在明文 HTTP(h2c)模式下需显式启用且浏览器不支持,生产环境几乎不用。
- 使用自签名证书或真实 TLS 证书均可触发 HTTP/2 协商
- 客户端(如 curl、Chrome)会通过 ALPN 协议自动协商
h2,无需服务端代码干预 - 若用
http.ListenAndServe(非 TLS),则永远只能是 HTTP/1.1
如何验证服务确实在用 HTTP/2
最直接的方式是看响应头或抓包。Go 本身不暴露协议版本到 http.Request,但可通过以下方式确认:
-
curl -I --http2 https://localhost:8080—— 若返回状态行带HTTP/2 200,说明成功 - Chrome DevTools → Network → 点开请求 → Headers → 查看
Protocol列是否为h2 - Wireshark 抓包过滤
http2或查看 TLS 握手时的 ALPN 字段是否含h2
注意:curl 必须是 7.47+ 且编译时启用了 nghttp2,否则 --http2 无效;macOS 上用 brew install curl-openssl 替换系统 curl 更可靠。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
HTTP/2 Server Push 怎么写(Go 1.8–1.22)
Go 原生支持 Server Push,但仅限于 HTTPS + HTTP/2 场景,且必须在 handler 中主动调用 Pusher.Push。不是所有响应都支持 push,比如重定向、流式响应中调用可能 panic。
func handler(w http.ResponseWriter, r *http.Request) {
if p, ok := w.(http.Pusher); ok {
if err := p.Push("/style.css", &http.PushOptions{
Method: "GET",
}); err != nil {
log.Println("push failed:", err)
// 忽略失败,继续正常响应
}
}
// 正常输出 HTML,其中引用 /style.css
io.WriteString(w, `<html><link rel="stylesheet" href="/style.css">...</html>`)
}
-
Pusher接口只在 HTTP/2 下可用,ok判断必不可少,否则 HTTP/1.1 请求会 panic - 被 push 的资源路径必须是绝对路径(以
/开头),且需匹配 server 的路由规则 - Go 1.23 起已标记
http.Pusher为 deprecated,未来可能移除;新项目建议用资源内联或 preload 替代
为什么本地测试时 curl 显示 HTTP/1.1?
常见原因有三个,按优先级排查:
- 没用 HTTPS:用
http.ListenAndServeTLS,而不是http.ListenAndServe - TLS 证书不被信任:自签名证书需加
-k(如curl -k --http2 https://localhost:8080),否则 curl 拒绝协商 HTTP/2 - Go 版本低于 1.8:老版本即使配了 TLS 也不会启用 HTTP/2,
go version必须确认
如果以上都满足,但 Chrome 仍显示 http/1.1,检查是否启用了「QUIC」协议干扰(chrome://flags/#enable-quic 关掉再试);或者服务端 Server.TLSConfig.NextProtos 被意外覆盖 —— 默认值包含 h2,手动设置时务必保留它。

















