Сетевой вызов завершился ошибкой контекста: как вызывающему отличить отмену операции от истечения дедлайна без анализа текста ошибки?
Используйте errors.Is с проверяемыми значениями context.Canceled и context.DeadlineExceeded. Этот подход сохраняет смысл ошибки даже после её оборачивания дополнительным контекстом.
Отмена обычно означает, что работу следует немедленно прекратить без повтора. Истечение дедлайна также не должно автоматически приводить к повтору: решение зависит от оставшегося общего времени, типа операции и политики сервиса.
В распределённых системах операция часто состоит из нескольких вызовов, выполняющихся в рамках одного запроса. Без единого контекста отдельные функции не могли надёжно узнать, что вызывающий уже отменил работу или что на операцию истёк отведённый срок.
Пакет context стандартизировал передачу сигнала отмены и дедлайна через стек вызовов. Значения context.Canceled и context.DeadlineExceeded дают вызывающему устойчивые категории ошибок вместо зависимости от текстовых сообщений конкретной библиотеки.
Низкоуровневая функция может добавить к ошибке сведения о ресурсе, операции или удалённом узле. Если верхний уровень сравнивает результат только через ==, такая обёртка скроет исходное значение, хотя причина останется той же.
Проверка текста ещё менее надёжна: сообщение может измениться из-за версии библиотеки, локализации или добавления диагностического контекста. Ошибочная классификация приводит к неправильной политике: например, к повтору уже отменённой операции или к выдаче пользователю сообщения о внутреннем сбое вместо корректного статуса отмены.
errors.Is проходит по цепочке обёрток, используя метод Unwrap, поэтому корректно распознаёт контекстную причину независимо от добавленного контекста. Проверки нужно выполнять отдельно: сначала определить отмену, затем истечение дедлайна, если приложению важно различать эти случаи.
Если функция добавляет контекст, она должна сохранять исходную ошибку в цепочке через механизм wrapping с поддержкой Unwrap. Простое форматирование текста без сохранения причины лишает вызывающий код возможности применить errors.Is.
Важно отличать причину завершения контекста от любой сетевой ошибки. Тайм-аут конкретной сетевой операции не всегда означает, что истёк дедлайн переданного контекста; классифицировать следует именно возвращённую цепочку причин и контракт используемой библиотеки.
Сервис вызывает платёжный шлюз с контекстом запроса. Пользователь закрыл страницу, и операция вернула обёрнутую ошибку с причиной context.Canceled.
Первый вариант — искать в тексте слова вроде «cancel» или «timeout». Он прост, но ломается при изменении формулировок и не различает гарантированно отмену и дедлайн. Второй вариант — сравнивать ошибку через ==; он работает только при отсутствии обёрток и потому ненадёжен для многоуровневого сервиса.
Выбран вариант с errors.Is. При отмене сервис прекращает ожидание результата и не запускает повторную оплату, а при дедлайне возвращает управляемый результат согласно политике операции. Это уменьшает риск дублирования платежа и сохраняет корректную семантику отмены.
Нет. Отмена вызывающим и истечение дедлайна — разные причины завершения. Первая обычно означает явное прекращение интереса к результату, а вторая — превышение временного бюджета; они могут требовать разных метрик, статусов и правил повторной попытки.
Единого порядка для всех функций нет, но контракт должен быть явным. Если функция обязана отдавать причину отмены при завершении контекста, проверка контекстной причины помогает не замаскировать её вторичной ошибкой. Если же уже подтверждённая бизнес-ошибка важнее для доменного контракта, приоритет может быть другим; главное — последовательно документировать правило.
errors.Is не сможет распознать отмену, потому что в цепочке не будет исходного значения и доступного через Unwrap перехода к нему. Верхний уровень увидит лишь обычную ошибку и может ошибочно выполнить повтор или записать неверную метрику. Обёртка должна сохранять причинную связь, а не только копировать текст сообщения.