go net/http: ListenAndServe example deadlocks in playground

3lxsmp7m  于 4个月前  发布在  Go
关注(0)|答案(6)|浏览(37)

你正在使用哪个版本的Go( go version )?

$ go version
go1.17.4

这个问题在最新版本中是否会重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env

你做了什么?

运行了适用于net/http.ListenAndServe()( https://play.golang.org/p/j01H9doftSz )的go playground示例

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [IO wait]:
internal/poll.runtime_pollWait(0x7f004b011eb8, 0x72)
	/usr/local/go-faketime/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000134000, 0x4, 0x0)
	/usr/local/go-faketime/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go-faketime/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000134000)
	/usr/local/go-faketime/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000134000)
	/usr/local/go-faketime/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00000c0f0)
	/usr/local/go-faketime/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00000c0f0)
	/usr/local/go-faketime/src/net/tcpsock.go:262 +0x3d
net/http.(*Server).Serve(0xc000132000, {0x6962b0, 0xc00000c0f0})
	/usr/local/go-faketime/src/net/http/server.go:3002 +0x394
net/http.(*Server).ListenAndServe(0xc000132000)
	/usr/local/go-faketime/src/net/http/server.go:2931 +0x7d
net/http.ListenAndServe(...)
	/usr/local/go-faketime/src/net/http/server.go:3185
main.main()
	/tmp/sandbox528359240/prog.go:20 +0xb4

Program exited.

你期望看到什么?

Hello, world!

你实际上看到了什么?

如上所述

ryevplcw

ryevplcw1#

它不是错误的?如果你假设唯一会接受的连接来自程序本身(据信在假想世界中是有效的假设),那么它确实陷入了僵局。
把服务器推到后台,并对其进行实际调用似乎有效:
$x_{1e0f1}x$

edqdpe6u

edqdpe6u2#

感谢查看!

所以,这个TL;DR是,我正在用手机和某人聊天,觉得http.ListenAndServe()是一个很好的例子来展示“这就是让Go变得美好的事情之一!”。然后点击了“运行示例”,看到了丑陋的跟踪(这可能不是那个例子的意图,而且很可能会让用户感到困惑)。

你更新的示例看起来不错(甚至可能更好,因为它是一个更完整的示例);稍微担心添加的复杂性是否会分散人们对http.ListenAndServe()主题本身的注意力。

qeeaahzv

qeeaahzv3#

顺便说一下,我认为这个更新可能实际上是不合适的。(我不确定如果 http.Get 协程在 ListenAndServe 协程打开套接字之前执行会发生什么。)
如果你打算使用 ListenAndServe 为具有实际测试的应用程序编写代码,你可能需要编写一个自旋循环,等待服务器启动后再开始测试。在我看来,更符合人体工程学的做法是分别使用 net.Listenhttp.Serve,这样你可以在启动对它的请求之前建立 Listener

disho6za

disho6za4#

一个更恰当的例子可能是类似于https://go.dev/play/p/UFd9OAIjx_B的东西。

rseugnpd

rseugnpd5#

这与playground下拉菜单中的"Http Server"示例几乎相同。

lqfhib0f

lqfhib0f6#

所以就是这样。完美!
然后也许我们应该用一个弃用通知来替换 ListenAndServe 示例。😁

相关问题