猿问

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

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要产生错误,则会由于数据竞争导致不一致的结果。


PIPIONE
浏览 194回答 2
2回答

呼啦一阵风

http.Serve 要么在调用后立即返回错误,要么在成功执行时阻塞这个假设是不正确的。而且我相信它很少发生。循环中的http.Serve调用net.Listener.Accept- 任何时候都可能发生错误(套接字关闭、打开的文件描述符过多等)。它http.ListenAndServe通常用于运行 http 服务器,在绑定侦听套接字时通常会提前失败(没有权限,地址已在使用中)。在我看来,您尝试做的事情是错误的,除非您net.Listener.Accept出于某种原因在第一次通话时确实失败了。是吗?如果你想 100% 确定你的服务器正在工作,你可以尝试连接到它(并且可能实际上传输一些东西),但是一旦你成功绑定了套接字,我认为它真的没有必要。

犯罪嫌疑人X

您可以在选择语句上使用超时,例如timeout := time.After(5 * time.Millisecond) // TODO: ajust the valueselect {case err := <-serveErr:&nbsp; &nbsp; return errcase _ := <- timeout:&nbsp; &nbsp; return nil}这样你的选择将被阻塞,直到serveErr有一个值或指定的值timeout已经过去。请注意,您的函数的执行将因此在指定的超时时间内阻塞调用 goroutine。Rob Pike 关于并发模式的精彩演讲可能会有所帮助。
随时随地看视频慕课网APP

相关分类

Go
我要回答