Метод http.Request.WithContext

Метод http.Request.WithContext создает новый экземпляр запроса, копируя все поля исходного запроса, но с указанным контекстом. В качестве параметра метод принимает новый контекст context.Context, который будет использован для управления временем выполнения запроса, отменой операций и передачей значений между компонентами приложения. Метод возвращает новый указатель на http.Request.

Синтаксис

goreq.WithContext(ctx)

Пример

Давайте создадим запрос с контекстом, который автоматически отменится через 5 секунд:

gopackage main

import (
  "context"
  "fmt"
  "net/http"
  "time"
)

func main() {
  req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
  if err != nil {
    fmt.Println(err)
    return
  }

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

  reqWithCtx := req.WithContext(ctx)

  fmt.Println(reqWithCtx.Context().Done())
}

Пример

Используем контекст для передачи пользовательских данных в запросе:

gopackage main

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

type userIDKey struct{}

func main() {
  ctx := context.WithValue(context.Background(), userIDKey{}, "12345")

  req, err := http.NewRequest(http.MethodGet, "https://api.example.com/profile", nil)
  if err != nil {
    fmt.Println(err)
    return
  }

  reqWithCtx := req.WithContext(ctx)

  userID := reqWithCtx.Context().Value(userIDKey{})
  fmt.Println(userID)
}

Результат выполнения кода:

go"12345"

Пример

Создаем запрос с контекстом и выполняем его, проверяя ошибку отмены:

gopackage main

import (
  "context"
  "fmt"
  "net/http"
  "time"
)

func main() {
  req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
  if err != nil {
    fmt.Println(err)
    return
  }

  ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  defer cancel()

  req = req.WithContext(ctx)

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer resp.Body.Close()

  fmt.Println(resp.StatusCode)
}

Результат выполнения кода при превышении таймаута:

gocontext deadline exceeded

Смотрите также

  • метод http.Request.Context,
    который возвращает текущий контекст запроса
  • метод http.Request.Clone,
    который создает глубокую копию запроса с контекстом
  • функцию http.NewRequestWithContext,
    которая создает запрос с контекстом
  • функцию http.Client.Do,
    которая выполняет запрос с учетом контекста