httptest.Server.Close 在 Go 1.23 上开启 keep-alive 时有可能卡住吗?我跑的是 go test -timeout 5s ./...,新写的测试既不通过也不失败。它一直挂到超时,然后我拿到 panic: test timed out after 5s 和 goroutine dump,quickfix 里一点断言的文字都没有。
dump 里,测试 goroutine 停在 httptest.(*Server).Close,在 sync.WaitGroup.Wait 里等着,是被我 defer 的 srv.Close() 调用的。handler goroutine 在 chan receive,第三个在 persistConn.roundTrip 里的 select。
-count=1、-race 和 DisableKeepAlives 都没有任何变化。同一个文件里的 JSON 测试是能过的。
gate := make(chan struct{})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-gate // gateway holds the ack
w.WriteHeader(http.StatusAccepted)
}))
defer srv.Close()
c := NewClient(srv.URL, log.New(io.Discard, "", 0))
errc := make(chan error, 1)
go func() { errc <- c.Send(context.Background(), testBatch()) }()
time.Sleep(100 * time.Millisecond)
if got := c.Pending(); got != 1 {
t.Fatalf("Pending() = %d while ack is held, want 1", got)
}
close(gate)
为什么 Close 会在这里阻塞,我的失败信息又跑哪去了?
从英语翻译·查看原文Is it possible that httptest.Server.Close hangs on Go 1.23 with keep-alive? I run go test -timeout 5s ./... and the new test neither passes nor fails. It sits until the timeout, then I get panic: test timed out after 5s and the goroutine dump, and no assertion text anywhere in quickfix.
In the dump, the test goroutine is in httptest.(*Server).Close, waiting in sync.WaitGroup.Wait, called from my deferred srv.Close(). The handler goroutine is in chan receive, and a third is in select inside persistConn.roundTrip.
-count=1, -race and DisableKeepAlives change nothing. The JSON test in the same file passes.
gate := make(chan struct{})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-gate // gateway holds the ack
w.WriteHeader(http.StatusAccepted)
}))
defer srv.Close()
c := NewClient(srv.URL, log.New(io.Discard, "", 0))
errc := make(chan error, 1)
go func() { errc <- c.Send(context.Background(), testBatch()) }()
time.Sleep(100 * time.Millisecond)
if got := c.Pending(); got != 1 {
t.Fatalf("Pending() = %d while ack is held, want 1", got)
}
close(gate)
Why would Close block here, and where did my failure message go?