http.Serve 要么在调用后立即返回错误,要么在成功执行时阻塞。我怎样才能让它在它自己的 goroutine 中阻塞它呢?我目前有以下代码:func serveOrErr(l net.Listener, handler http.Handler) error { starting := make(chan struct{}) serveErr := make(chan error) go func() { starting <- struct{}{} if err := http.Serve(l, handler); err != nil { serveErr <- err } }() <-starting select { case err := <-serveErr: return err default: return nil }}这似乎是一个好的开始,并且在我的测试机器上工作,但我相信没有任何保证serveErr <- err会在之前调用,case err := <-serveErr因此如果http.Serve要产生错误,则会由于数据竞争导致不一致的结果。
2 回答
呼啦一阵风
TA贡献1802条经验 获得超6个赞
http.Serve 要么在调用后立即返回错误,要么在成功执行时阻塞
这个假设是不正确的。而且我相信它很少发生。循环中的http.Serve
调用net.Listener.Accept
- 任何时候都可能发生错误(套接字关闭、打开的文件描述符过多等)。它http.ListenAndServe
通常用于运行 http 服务器,在绑定侦听套接字时通常会提前失败(没有权限,地址已在使用中)。
在我看来,您尝试做的事情是错误的,除非您net.Listener.Accept
出于某种原因在第一次通话时确实失败了。是吗?如果你想 100% 确定你的服务器正在工作,你可以尝试连接到它(并且可能实际上传输一些东西),但是一旦你成功绑定了套接字,我认为它真的没有必要。
犯罪嫌疑人X
TA贡献2080条经验 获得超4个赞
您可以在选择语句上使用超时,例如
timeout := time.After(5 * time.Millisecond) // TODO: ajust the value
select {
case err := <-serveErr:
return err
case _ := <- timeout:
return nil
}
这样你的选择将被阻塞,直到serveErr有一个值或指定的值timeout已经过去。请注意,您的函数的执行将因此在指定的超时时间内阻塞调用 goroutine。
Rob Pike 关于并发模式的精彩演讲可能会有所帮助。
- 2 回答
- 0 关注
- 193 浏览
添加回答
举报
0/150
提交
取消