Контекст: В backend/internal/handlers/errors.go:13 объявлена глобальная переменная var AppEnv string, которая устанавливается из cmd/api/main.go:68. Используется для контроля раскрытия деталей ошибок в production.
// handlers/errors.go — ❌ package-level mutable state
var AppEnv string
func writeError(w http.ResponseWriter, status int, msg string, err error) {
if status == http.StatusInternalServerError && AppEnv == "production" {
msg = "internal server error"
}
writeJSON(w, status, map[string]string{"error": msg})
}
// cmd/api/main.go:68 — установка глобальной переменной
handlers.AppEnv = cfg.AppEnv
Антипаттерн:
writeError в production-режиме нужно установить AppEnv = "production", а потом сбросить. При параллельных тестах — race condition.AppEnv в любой момент. Нет гарантии консистентности.Передавать isProd через конструктор хендлера (как уже сделано в AuthHandler):
type PlaceHandler struct {
placeSvc *services.PlaceService
isProd bool // ✅ явная зависимость
}
func NewPlaceHandler(placeSvc *services.PlaceService, isProd bool) *PlaceHandler {
return &PlaceHandler{placeSvc: placeSvc, isProd: isProd}
}
func (h *PlaceHandler) writeError(w http.ResponseWriter, status int, msg string, err error) {
if status == http.StatusInternalServerError && h.isProd {
msg = "internal server error"
}
writeJSON(w, status, map[string]string{"error": msg})
}
| Подход | Плюсы | Минусы |
|---|---|---|
| DI через конструктор (рекомендую) | Тестируемо, явно, потокобезопасно | Нужно менять все хендлеры |
| Context values | Не меняет сигнатуры хендлеров | Неявно, .Value() без проверки типа |
| Оставить как есть (status quo) | Нет работы | Нет тестов, race condition |
AppEnvCode review PhotoPlaces 2026-06. Найдено в handlers/errors.go:13.
#architecture #anti-pattern #testing #golang #clean-code