README
¶
Go Errors Package
Пакет ошибок Go предоставляет расширенный способ обработки ошибок в микросервисах, полностью совместимый со стандартным пакетом errors из Go 1.13+. Он включает единый тип ошибки с поддержкой HTTP-кодов состояния, JSON-представления и интеграцией с errors.Is/errors.As.
Основные возможности
-
Полная совместимость со стандартным пакетом errors:
- Поддержка
errors.Is
иerrors.As
для проверки и приведения типов ошибок - Поддержка
errors.Unwrap
для цепочек ошибок - Взаимодействие со стандартными ошибками Go
- Поддержка
-
HTTP-интеграция и API:
- Единый тип
Error
с HTTP-кодами состояния и JSON-представлением - Предопределенные ошибки для типичных HTTP-сценариев
- Функции для автоматического форматирования HTTP-ответов
- Единый тип
-
Удобное API для работы с ошибками:
- Методы для кастомизации сообщений и метаданных
- Функции для оборачивания стандартных ошибок Go
- Константы HTTP-кодов, совместимые с пакетом net/http
-
Интеграция с веб-фреймворками и логированием:
- Примеры использования с Fiber через middleware
- Поддержка стандартного http.Handler
- Простое логирование цепочек ошибок в консольных приложениях
- Интеграция с Fiber logger для структурированного логирования
Установка
go get github.com/Vova4o/go-errors
Использование
1. Создание и использование ошибок
import "github.com/Vova4o/go-errors/errors"
// Создание новой ошибки с HTTP-кодом
err := errors.NewError(errors.StatusBadRequest, "Неверный формат JSON", nil)
// Использование предопределенной ошибки
err = errors.ErrNotFound
// Кастомизация сообщения ошибки
err = errors.ErrNotFound.WithMessage("Пользователь с ID 123 не найден")
// Оборачивание стандартной ошибки Go
baseErr := stderrors.New("timeout after 30s")
err = errors.Wrap(baseErr, errors.StatusGatewayTimeout, "Ошибка подключения к БД")
2. Совместимость со стандартным пакетом errors
import (
stderrors "errors" // стандартный пакет errors
"go-errors-package/errors" // наш пакет
)
// Проверка типа ошибки через errors.Is
if stderrors.Is(err, errors.ErrNotFound) {
// Обработка "не найдено"
}
// Мы также предоставляем прокси для стандартных функций
if errors.Is(err, errors.ErrNotFound) {
// То же самое, что и выше
}
// Извлечение дополнительной информации через errors.As
var customErr errors.Error
if stderrors.As(err, &customErr) {
log.Printf("HTTP код: %d, сообщение: %s", customErr.Code, customErr.Message)
}
// Работа с цепочкой ошибок
originalErr := stderrors.Unwrap(err)
// Или с помощью нашего прокси
originalErr = errors.Unwrap(err)
3. Обработка HTTP-ответов
func Handler(w http.ResponseWriter, r *http.Request) {
result, err := processRequest(r)
if err != nil {
// Автоматическая обработка любого типа ошибок
errors.HandleHTTPResponse(w, err)
return
}
// Отправка успешного ответа
errors.WriteSuccessResponse(w, result)
}
4. Интеграция с Fiber через Middleware
// Middleware для обработки ошибок
func ErrorHandler() fiber.Handler {
return func(c *fiber.Ctx) error {
err := c.Next()
if err == nil {
return nil
}
statusCode := fiber.StatusInternalServerError
errorResponse := fiber.Map{
"status": "ERROR",
"message": "Internal server error",
}
var customErr errors.Error
if stderrors.As(err, &customErr) {
statusCode = customErr.Code
errorResponse["status"] = customErr.Status
errorResponse["message"] = customErr.Message
// Логирование с распаковкой цепочки ошибок
logError(c, customErr)
} else {
errorResponse["message"] = err.Error()
}
return c.Status(statusCode).JSON(errorResponse)
}
}
// Использование в приложении
app := fiber.New()
app.Use(ErrorHandler())
app.Get("/users/:id", getUserHandler)
5. Логирование ошибок в консольных приложениях
// Простой логер для консольных приложений
type ErrorLogger struct {
prefix string
}
// Метод для логирования ошибок с распаковкой цепочки
func (l *ErrorLogger) Log(err error) {
if err == nil {
return
}
// Вывод основной информации об ошибке
fmt.Printf("[%s] ERROR: ", l.prefix)
// Проверяем, является ли ошибка нашей структурированной ошибкой
var customErr errors.Error
if stderrors.As(err, &customErr) {
fmt.Printf("[%d] %s\n", customErr.Code, customErr.Message)
// Распаковка цепочки ошибок для отладки
cause := customErr.Unwrap()
indent := " "
for cause != nil {
fmt.Printf("%s↳ %v\n", indent, cause)
cause = stderrors.Unwrap(cause) // Используем стандартную функцию Unwrap
indent += " "
}
} else {
// Обычная ошибка Go
fmt.Printf("%v\n", err)
}
}
// Пример использования
logger := &ErrorLogger{prefix: "APP"}
// Создание цепочки ошибок
baseErr := stderrors.New("timeout error")
dbErr := errors.Wrap(baseErr, errors.StatusServiceUnavailable, "Ошибка БД")
serviceErr := errors.Wrap(dbErr, errors.StatusInternalServerError, "Ошибка сервиса")
// Логирование
logger.Log(serviceErr)
// Выведет:
// [APP] ERROR: [500] Ошибка сервиса
// ↳ Ошибка БД: timeout error
// ↳ timeout error
6. Интеграция с Fiber Logger
Если вы предпочитаете использовать структурированное логирование, вы можете легко интегрировать наш пакет ошибок с Fiber Logger:
import (
stderrors "errors"
"github.com/gofiber/fiber/v2/log"
customerrors "gitlab.com/multispek/go-errors-package/errors"
)
// Функция для форматирования цепочки ошибок
func formatErrorChain(err error) string {
if err == nil {
return ""
}
var customErr customerrors.Error
if customerrors.As(err, &customErr) {
// Базовая информация об ошибке
result := fmt.Sprintf("[%d] %s", customErr.Code, customErr.Message)
// Разворачиваем и форматируем цепочку ошибок
var causes []string
cause := customErr.Unwrap()
indent := " "
for cause != nil {
causes = append(causes, fmt.Sprintf("%s↳ %v", indent, cause))
cause = stderrors.Unwrap(cause)
indent += " "
}
if len(causes) > 0 {
result += "\n" + strings.Join(causes, "\n")
}
return result
}
return err.Error()
}
// Пример логирования ошибки с использованием Fiber logger
func handleError(err error) {
var customErr customerrors.Error
if customerrors.As(err, &customErr) {
// Структурированное логирование с дополнительными метаданными
log.Errorw(customErr.Message,
"statusCode", customErr.Code,
"service", "UserService",
"errorChain", formatErrorChain(customErr.Unwrap()))
} else {
log.Error(err.Error())
}
}
// Пример использования в коде
func processUser(id string) error {
if id == "" {
return customerrors.ErrBadRequest.WithMessage("ID не может быть пустым")
}
// Предположим, что произошла ошибка при обращении к БД
dbErr := stderrors.New("connection timeout")
return customerrors.Wrap(dbErr, customerrors.StatusServiceUnavailable,
"Ошибка при получении пользователя")
}
// Использование в обработчике
func userHandler(c *fiber.Ctx) error {
id := c.Params("id")
err := processUser(id)
if err != nil {
handleError(err)
return err // Fiber middleware обработает HTTP-ответ
}
return c.JSON(fiber.Map{"success": true})
}
Структура пакета
errors/
├── constants.go - HTTP коды состояния
├── predefined.go - Предопределенные ошибки
├── service_error.go - Основной тип Error
├── handler.go - HTTP-обработчики
└── doc.go - Документация
Примеры
В каталоге examples
вы найдёте полные примеры использования пакета:
main.go
- базовые примеры использования пакетаfiber_example.go
- пример интеграции с фреймворком Fiberlogging_example.go
- пример логирования ошибок (с вариантами для консольных приложений и через Fiber logger)
Для запуска примеров:
go run examples/main.go
go run examples/fiber_example.go
go run examples/logging_example.go
Цепочки ошибок и Unwrap
Пакет полностью поддерживает создание цепочек ошибок и стандартные механизмы работы с ними:
// Ошибка в репозитории
dbErr := stderrors.New("connection timeout")
repoErr := errors.Wrap(dbErr, errors.StatusInternalServerError, "Ошибка БД")
// Ошибка в сервисном слое
serviceErr := errors.Wrap(repoErr, errors.StatusInternalServerError, "Ошибка сервиса")
// В обработчике HTTP:
// 1. Получаем код и сообщение для клиента
statusCode, message := errors.ToHTTPError(serviceErr) // 500, "Ошибка сервиса: Ошибка БД: connection timeout"
// 2. Для отладки можем получить всю цепочку через Unwrap
cause := serviceErr
for cause != nil {
fmt.Printf("-> %v\n", cause)
cause = stderrors.Unwrap(cause)
}
// Выведет:
// -> Ошибка сервиса: Ошибка БД: connection timeout
// -> Ошибка БД: connection timeout
// -> connection timeout
Лицензия
Этот проект распространяется под лицензией MIT. См. файл LICENSE для более подробной информации.
Directories
¶
Path | Synopsis |
---|---|
Package errors предоставляет расширенную обработку ошибок для HTTP API и микросервисов, совместимую со стандартным пакетом errors Go 1.13+.
|
Package errors предоставляет расширенную обработку ошибок для HTTP API и микросервисов, совместимую со стандартным пакетом errors Go 1.13+. |
Пример использования пакета ошибок с фреймворком Fiber
|
Пример использования пакета ошибок с фреймворком Fiber |