本指南解决了 Go 的 HTTP 响应处理中的缓冲问题,其中响应通常被缓冲并以块的形式发送到处理请求后的客户端。对于流式传输场景,这可能并不理想。
提供的代码片段说明了问题,其中两行数据应该被流式传输,但由于缓冲而同时发送。
解决此问题的一种方法是显式刷新响应缓冲区。 Go 的 ResponseWriter 提供了 Flush 方法,但其可用性取决于具体实现。
例如,以下修改后的代码包含刷新:
func handle(res http.ResponseWriter, req *http.Request) { fmt.Fprintf(res, "sending first line of data") if f, ok := res.(http.Flusher); ok { f.Flush() } sleep(10) //not real code fmt.Fprintf(res, "sending second line of data") }
在某些场景下,例如流式传输外部命令的输出,直接刷新可能不够。 Go 的管道机制允许在命令的输出和响应编写器之间进行直接流式传输。
这是一个示例实现:
pipeReader, pipeWriter := io.Pipe() cmd.Stdout = pipeWriter cmd.Stderr = pipeWriter go writeCmdOutput(res, pipeReader) err := cmd.Run() pipeWriter.Close() func writeCmdOutput(res http.ResponseWriter, pipeReader *io.PipeReader) { buffer := make([]byte, BUF_LEN) for { n, err := pipeReader.Read(buffer) if err != nil { pipeReader.Close() break } data := buffer[0:n] res.Write(data) if f, ok := res.(http.Flusher); ok { f.Flush() } //reset buffer for i := 0; i < n; i++ { buffer[i] = 0 } } }
为了获得更大的灵活性,可以使用 TCP 劫持者,它可以直接控制 TCP 连接。然而,这种方法需要对网络编程有更深入的了解,并且不太推荐用于一般用例。
请注意,缓冲仍然可能发生在网络组件或客户端应用程序中,因此它是对于评估您的具体用例以确定是否需要显式冲洗或替代解决方案至关重要。
以上是如何在 Golang 中传输 HTTP 响应并避免默认缓冲?的详细内容。更多信息请关注PHP中文网其他相关文章!