Ошибка context.Canceled

Ошибка context.Canceled представляет собой предопределенную переменную ошибки, которая возвращается функцией Context.Err при вызове на отмененном контексте. Эта ошибка сигнализирует о том, что контекст был отменен до завершения операции, которая с ним связана. Обычно она возникает в длительных операциях, поддерживающих отмену через контекст, таких как HTTP-запросы, обработка данных или работа с базами данных.

Основная причина возникновения ошибки context.Canceled - явный вызов функции отмены, возвращенной context.WithCancel или аналогичными функциями, либо истечение таймаута при использовании context.WithTimeout или context.WithDeadline. При получении этой ошибки следует корректно завершить выполнение текущей операции и освободить ресурсы.

Синтаксис

govar Canceled = errors.New("context canceled")

Ошибка context.Canceled является глобальной переменной пакета context и может использоваться для сравнения с ошибкой, возвращаемой методом Err отмененного контекста.

Пример

Создадим контекст с отменой, вызовем функцию отмены и проверим ошибку:

gopackage main

import (
  "context"
  "fmt"
)

func main() {
  ctx, cancel := context.WithCancel(context.Background())
  cancel() // Отменяем контекст

  err := ctx.Err()
  if err == context.Canceled {
    fmt.Println("Контекст был отменен")
  }
}

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

go"Контекст был отменен"

Пример

Используем context.WithTimeout и дождемся истечения таймаута:

gopackage main

import (
  "context"
  "fmt"
  "time"
)

func main() {
  ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
  defer cancel()

  time.Sleep(20 * time.Millisecond)

  err := ctx.Err()
  if err == context.Canceled {
    fmt.Println("Контекст был отменен")
  } else {
    fmt.Printf("Ошибка: %v", err)
  }
}

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

go"Контекст был отменен"

Пример

Обработка ошибки context.Canceled при выполнении длительной операции:

gopackage main

import (
  "context"
  "fmt"
  "time"
)

func longOperation(ctx context.Context) error {
  select {
  case <-time.After(2 * time.Second):
    return fmt.Errorf("операция завершена")
  case <-ctx.Done():
    return ctx.Err()
  }
}

func main() {
  ctx, cancel := context.WithCancel(context.Background())

  go func() {
    time.Sleep(100 * time.Millisecond)
    cancel()
  }()

  err := longOperation(ctx)
  if err == context.Canceled {
    fmt.Println("Операция прервана из-за отмены контекста")
  } else if err != nil {
    fmt.Printf("Ошибка: %v", err)
  }
}

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

go"Операция прервана из-за отмены контекста"

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

  • функцию Context.Err,
    которая возвращает ошибку отмены контекста
  • функцию context.WithCancel,
    которая создает контекст с возможностью отмены
  • функцию context.WithTimeout,
    которая создает контекст с таймаутом
  • функцию Context.Done,
    которая возвращает канал для ожидания отмены контекста