Context timeout implementation on every request using golang

梦想的初衷 提交于 2019-12-02 21:07:33
Bogdan Iulian Bursuc

What happens in your code is very correct and behaves as expected.

You create a context with 5 seconds timeout. You pass it to the request and make that request. Let's say that request returns in 2 seconds. You then do a select and either wait 10 seconds or wait for the context to finish. Context will always finish in the initial 5 seconds from when it was created and will also give that error every time it reaches the end.

The context is independent of the request and it will reach it's deadline unless, cancelled previously. You cancel the request when the function finishes using defer.

In your code the request takes your timeout in consideration. But the ctx.Err() will return deadline exceeded everytime it reaches the timeout. Since that's what happens inside the context. calling ctx.Err() multiple times will return the same error.

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

go func () {
    select {
    case <-time.After(10 * time.Second):
        fmt.Println("overslept")
    case <-ctx.Done():
        fmt.Println(ctx.Err()) // prints "context deadline exceeded"
    }
}()
req, _ := http.NewRequest("GET", authorizationServer, nil)
req.Header = r.Header
req = req.WithContext(ctx)
res, error := client.Do(req)

From the context documentation:

// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.

In your code, the timeout will always be reached and not cancelled, that is why you receive DeadlineExceeeded. Your code is correct except the select part which will block until either 10 seconds pass or context timeout is reached. In your case always the context timeout is reached.

You should check the error returned by the client.Do call and not worry about the context error in here. You are the one controlling the context. If the request timeouts, a case you should test of course, then a proper error would be returned for you to verify.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!