
Go 语言中并发处理 HTTP 请求时,如果使用不当,可能会导致请求无响应。这是因为 net/http 包的 ListenAndServe 函数已经自动启动了 goroutine 来处理每个连接。重复启动 goroutine 反而会导致问题。
ListenAndServe 函数内部已经实现了并发处理机制。以下是相关源码的简化版本,重点关注 goroutine 的创建:
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
// ... handle error ...
continue
}
c := srv.newConn(conn)
go c.serve() // 关键:每个连接都在一个 goroutine 中处理
}
}
func (c *conn) serve() {
// ... connection setup ...
handler.ServeHTTP(w, c.req) // 调用你的 Handler
// ... connection cleanup ...
}可以看到,Serve 方法在一个无限循环中接受新的连接,并且为每个连接启动一个新的 goroutine 来处理。这个 goroutine 会调用你的 handler 函数来处理 HTTP 请求。
因此,在你的 handle 函数中,不应该再手动启动 goroutine。 这样做会引入不必要的并发,并且可能导致 ResponseWriter 在多个 goroutine 中被同时访问,从而引发竞争条件和未定义的行为,最终导致请求无响应。
正确的处理方式:
直接在 handle 函数中进行计算和响应,无需额外启动 goroutine。
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", handle)
http.ListenAndServe(":8080", nil)
}
func handle(w http.ResponseWriter, r *http.Request) {
// 模拟耗时计算
time.Sleep(1 * time.Second)
// 呈现结果
fmt.Fprint(w, "hello")
}代码解释:
注意事项:
总结:
Go 语言的 net/http 包已经提供了内置的并发处理机制。理解 ListenAndServe 函数的工作原理,避免重复启动 goroutine,是解决并发 HTTP 请求无响应问题的关键。 遵循最佳实践,可以编写出高效、稳定的并发 HTTP 服务器。
以上就是Go 并发 HTTP 请求无响应问题排查与解决的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号