From 1375ec921865cc8e485c7efc9eb3aa91705edb60 Mon Sep 17 00:00:00 2001 From: Fedorov Vladimir Date: Sat, 3 Oct 2026 01:44:27 +0700 Subject: [PATCH] update --- docs/GO_STANDARD.md | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/GO_STANDARD.md b/docs/GO_STANDARD.md index 08e7588..a8ffb1e 100644 --- a/docs/GO_STANDARD.md +++ b/docs/GO_STANDARD.md @@ -204,18 +204,40 @@ SQL держи рядом с методом, которому он нужен. ## 8. Ошибки и context - Возвращай ошибки, не паникуй в обработке пользовательского ввода, БД, - файлов, сети и внешних сервисов. -- Для ожидаемых веток объявляй sentinel-ошибку в пакете, который владеет - смыслом ошибки; проверяй её через `errors.Is`. + файлов, сети и внешних сервисов. `panic` допустим только для невозможного + нарушения внутреннего инварианта при старте или в коде, который не имеет + осмысленного способа продолжить работу. +- Ошибкой владеет пакет, которому принадлежит её смысл. Ожидаемые состояния + объявляй как sentinel-ошибки (`var Err... = errors.New(...)`) в сервисе, + repository или module; не дублируй одну смысловую ошибку в разных слоях. +- Repository переводит ошибки драйвера и ограничения БД в свои предметные + ошибки. Service переводит их в ошибки use case. `app` не меняет бизнес-смысл + ошибки, а только преобразует её в транспортный ответ. +- Для ожидаемых веток проверяй цепочку через `errors.Is`; для ошибок с данными + используй `errors.As`. Текст ошибки не сравнивай. - Оборачивай ошибку с контекстом через `%w`, например - `fmt.Errorf("загрузить сценарий %d: %w", id, err)`. -- Не сравнивай текст ошибки и не теряй исходную ошибку без причины. + `fmt.Errorf("загрузить сценарий %d: %w", id, err)`. Не теряй исходную ошибку + без причины и не оборачивай её повторно пустым или одинаковым сообщением. +- `status.Error` и `status.Errorf` используй только на транспортной границе + (`internal/app` или gRPC middleware). Services, repositories и modules не + возвращают gRPC-ошибки. +- Преобразование ошибок use case в gRPC-коды держи в `*_errors.go` рядом с + handler-ом. Для неизвестной ошибки возвращай `codes.Internal` с безопасным + общим сообщением; детали причины сохраняй в цепочке и логируй на внешней + границе. +- Клиенту нельзя отдавать SQL, пути файлов, адреса внешних сервисов, stack + trace, токены, пароли или персональные данные. Ошибки валидации могут + содержать только безопасные сведения, необходимые клиенту. +- Логируй ошибку один раз на границе, которая принимает решение о внешнем + ответе; нижние слои добавляют контекст через `%w`, но не дублируют лог. - Каждый внешний вызов получает переданный `context.Context`; timeout нужен на - границе долгой операции или фонового worker-а. + границе долгой операции или фонового worker-а. Отмену контекста не скрывай: + возвращай `ctx.Err()` или оборачивай её через `%w`. - Не помещай обязательные параметры операции в context. В context допустимы только request-scoped данные, уже принятые проектным middleware. -- Не логируй пароли, токены, персональные данные и содержимое пользовательских - файлов. +- Для каждой новой ветки бизнес-ошибки тестируй `errors.Is` и итоговый + транспортный код; для неизвестной ошибки проверяй, что наружу уходит + `codes.Internal` без внутренних деталей. ## 9. SQL и транзакции