为了账号安全,请及时绑定邮箱和手机立即绑定

如果 http.Serve 阻塞,如何将其放置在自己的 goroutine 中?

如果 http.Serve 阻塞,如何将其放置在自己的 goroutine 中?

Go
PIPIONE 2021-11-29 19:08:17
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% 确定你的服务器正在工作,你可以尝试连接到它(并且可能实际上传输一些东西),但是一旦你成功绑定了套接字,我认为它真的没有必要。


查看完整回答
反对 回复 2021-11-29
?
犯罪嫌疑人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 关于并发模式的精彩演讲可能会有所帮助。


查看完整回答
反对 回复 2021-11-29
  • 2 回答
  • 0 关注
  • 193 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信