Iris.Context.Write 不能直接实现 Chunked 传输,因其依赖手动设置 Transfer-Encoding: chunked、禁用 Gzip、提前写 header 并调用 ResponseWriter().Flush() 分批刷出;HTTP/2 下 Flush 无效,SSE 场景推荐使用 iris.Stream。

为什么 iris.Context.Write 不能直接实现 Chunked 传输
因为 Iris 默认使用 http.ResponseWriter 的底层写入机制,而 Go 标准库的 ResponseWriter 在调用 Write 前若未设置 Content-Length 且未显式启用分块,不会自动切换为 Transfer-Encoding: chunked —— 它可能缓冲、截断,甚至在写入中途 panic(比如已写 header 后再改状态码)。关键点在于:Chunked 不是“多调几次 Write”就能触发的,它依赖响应头控制和底层连接状态。
必须手动设置 Transfer-Encoding: chunked 并禁用压缩
Iris 默认启用 Gzip 压缩,而压缩中间件会接管写入流,彻底屏蔽 Chunked 行为。你得绕过它,并显式声明传输编码:
- 调用
ctx.ResponseWriter().Header().Set("Transfer-Encoding", "chunked") - 调用
ctx.Gzip(false)或在路由注册时关闭该 handler 的 gzip(推荐用iris.NoGzip中间件) - **不能**再调用
ctx.StatusCode()或ctx.ContentType()之后才设Transfer-Encoding,否则 header 已 flush,设置无效
用 ctx.ResponseWriter().Write 分批写入 + flush
Chunked 的本质是每写一段数据就 flush 一次,让 net/http 自动包成 size\r\n[data]\r\n 格式。Iris 没有封装 Flush() 的快捷方法,必须取原始 ResponseWriter:
ctx.ResponseWriter().Header().Set("Transfer-Encoding", "chunked")
ctx.Gzip(false)
ctx.StatusCode(200)
ctx.ContentType("text/event-stream") // 或你实际需要的 MIME
<p>// 开始写
for i := 0; i </p>
注意:Flush() 只在支持的底层连接(如 HTTP/1.1 明文)上生效;HTTP/2 会忽略它,走自己的流控 —— 所以 Chunked 主要用于兼容老客户端或 SSE 场景。
更安全的替代:用 iris.Stream 封装 SSE 流
如果你实际目标是服务端事件(SSE),别硬搞 Chunked。Iris 提供了 iris.Stream,它内部已处理 header、flush、错误中断和连接保活:
Content-Type: text/event-stream











