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
{1}}会产生错误。
答案 0 :(得分:4)
http.Serve在调用时会立即返回错误,如果成功执行则会阻塞
这个假设是不正确的。我相信它很少发生。 http.Serve
在循环中调用net.Listener.Accept
- 错误可能随时发生(套接字关闭,打开文件描述符太多等)。它的http.ListenAndServe
通常用于运行http服务器,它通常在绑定侦听套接字时提前失败(没有权限,地址已在使用中)。
在我看来,你尝试做的事情是错误的,除非你的net.Listener.Accept
因某种原因在第一次通话时失败了。是吗?如果你想100%确定你的服务器正在工作,你可以尝试连接它(也许实际上传输一些东西),但是一旦你成功绑定了套接字我就不会觉得它真的有必要。
答案 1 :(得分:1)
您可以在select语句中使用超时,例如
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关于go concurrency patterns的精彩演讲可能会有所帮助。