Обработка ошибок

В Go нет исключений. Ошибка — обычное значение, которое функция возвращает последним:

type error interface {
    Error() string
}
import "errors"

var ErrNotFound = errors.New("not found")

func find(id int) (string, error) {
    if id < 0 {
        return "", fmt.Errorf("некорректный id: %d", id)
    }
    if id > 100 {
        return "", ErrNotFound
    }
    return "item", nil
}

Ошибки можно оборачивать (%w), сохраняя цепочку:

if err := doSomething(); err != nil {
    return fmt.Errorf("шаг X: %w", err)
}

Развернуть цепочку:

if errors.Is(err, ErrNotFound) {
    // обработка конкретной ошибки
}

var e *PathError
if errors.As(err, &e) {
    fmt.Println(e.Path)
}

panic — нештатное завершение. Используется только для программных ошибок (инвариант нарушен). Пользовательский ввод, сетевые сбои — это error, не panic.

recover перехватывает панику внутри defer:

func safe(f func()) (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("паника: %v", r)
        }
    }()
    f()
    return
}

ЗаданиеСложность
1Упражнение 1easy
2Упражнение 2medium
3Упражнение 3medium