Как я могу отменить контекст для исходящего запроса клиента?

# #http #go #cancellation #go-context

Вопрос:

мой код такой:

 package main

import (
    "context"
    "fmt"
    "io"
    "net/http"
    "os"
)

var (
    client = http.DefaultClient
)

func do(pctx context.Context, req *http.Request) (*http.Response, error) {
    // in order to not capture the pctx.Done. the caller may capture the pctx.Done().
    ctx, cancel := context.WithCancel(pctx)
    defer cancel()

    req = req.WithContext(ctx)
    resp, err := client.Do(req)
    if err != nil {
        select {
        case <-ctx.Done():
            return nil, ctx.Err()
        }
    }
    return resp, err
}
func main() {
    req, err := http.NewRequest(http.MethodGet, "http://www.google.com", nil)
    if err != nil {
        panic(err)
    }
    resp, err := do(context.Background(), req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    _, err = io.Copy(os.Stdout, resp.Body)
    fmt.Println()
    fmt.Println()
    fmt.Println(err)
}
 

Это выводит

 $ go run .
<!doctype html><ht[...... removed for conciseness]
context canceled
 

Этот код неверен. контекст будет отменен, когда я прочитаю данные из соотв.тела, Как я могу отменить контекст, будет ли контекст автоматически отменен во время обработки http-запроса ?
Спасибо.

Комментарии:

1. Если вы позвоните cancel (в отдельном режиме), пока client.Do активны, запрос будет прерван. В чем, собственно, вопрос?

2. Поскольку, в моем понимании, я создал контекст, я должен закрыть его сам. Это правильно? или, если я не отменю контекст, он не сможет вызвать утечку памяти.

3. Проблема в том, что вы отменили функцию context ( defer cancel ) до того, как тело ответа было полностью прочитано. Вы должны отменить контекст только после того, как отправили запрос, и полностью прочитать его ответ.