Go
Обработка ошибок: обёртки и errors.Is/As
Идиоматичный Go: добавление контекста через %w, собственные типы ошибок и их проверка.
Код
package main
import (
"errors"
"fmt"
"os"
)
var ErrNotFound = errors.New("не найдено")
// Собственный тип ошибки с дополнительными полями
type ValidationError struct {
Field string
Reason string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("поле %q: %s", e.Field, e.Reason)
}
func loadUser(id int) error {
if id <= 0 {
return &ValidationError{Field: "id", Reason: "должен быть положительным"}
}
if _, err := os.ReadFile(fmt.Sprintf("users/%d.json", id)); err != nil {
// %w сохраняет исходную ошибку в цепочке
return fmt.Errorf("загрузка пользователя %d: %w", id, err)
}
return nil
}
func main() {
err := loadUser(42)
// Сравнение с конкретной ошибкой по цепочке
if errors.Is(err, os.ErrNotExist) {
fmt.Println("файла нет:", err)
}
// Извлечение типизированной ошибки
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("ошибка валидации поля:", ve.Field)
}
// Объединение нескольких ошибок (Go 1.20+)
combined := errors.Join(ErrNotFound, err)
fmt.Println(errors.Is(combined, ErrNotFound)) // true
}