🚨 Ошибки в Go — часть обычного потока
В Go нет исключений, как в других языках. Вместо этого Go использует значения ошибок — это простой, но мощный способ обработки проблем.
📦 Тип error
Тип error — это встроенный интерфейс:
type error interface {
    Error() string
}
Функции возвращают ошибку как второе значение:
value, err := someFunc()
if err != nil {
    fmt.Println("Произошла ошибка:", err)
    return
}
🛠 Создание ошибок
Создать простую ошибку можно с помощью errors.New:
import "errors"
err := errors.New("что-то пошло не так")
Или с форматированием:
import "fmt"
err := fmt.Errorf("ошибка: %v", cause)
📏 Пример с возвратом ошибки
func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("деление на ноль")
    }
    return a / b, nil
}
result, err := divide(10, 0)
if err != nil {
    fmt.Println("Ошибка:", err)
} else {
    fmt.Println("Результат:", result)
}
🔧 Свои типы ошибок
Ты можешь определить собственные типы ошибок:
type MyError struct {
    Code int
    Msg  string
}
func (e MyError) Error() string {
    return fmt.Sprintf("код %d: %s", e.Code, e.Msg)
}
Использование:
return MyError{Code: 404, Msg: "Не найдено"}
⛔ Panic и recover (продвинуто)
Иногда ошибки критичны, и программа должна завершиться. Тогда используют panic:
panic("фатальная ошибка")
panic можно перехватить с помощью recover, но это используется редко — например, в middleware:
func safeExecute() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Восстановление после паники:", r)
        }
    }()
    panic("что-то пошло не так")
}
📌 Главное из главы
- Ошибки — обычная часть работы функций в Go.
 - Проверяй 
err != nilпосле каждой операции. - Используй 
fmt.Errorfиerrors.Newдля создания ошибок. - Определяй свои типы ошибок для сложных случаев.
 panic/recover— только для экстренных ситуаций.
В следующем разделе ты узнаешь, что такое параллелизм и каналы, а так же про паттерны конкурентности.