> Для чего используется пакет errors в Go (Go)

Уровень: middle · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Lamoda

Стек: Go

> Пример ответа

Короткий ответ

Пакет errors в Go используется для создания ошибок, их обёртывания и проверки. Основные функции: errors.New - создание простой ошибки, errors.Is - проверка на конкретную ошибку в цепочке, errors.As - приведение к определённому типу, errors.Unwrap - получение предыдущей ошибки. Пакет появился в Go 1.13 и стал стандартным инструментом для работы с ошибками вместо ручных сравнений и кастомных обёрток.

Подробное объяснение

До Go 1.13 работа с ошибками была ограничена: можно было только создавать их через errors.New или fmt.Errorf без %w. Проверка на конкретную ошибку требовала сравнения значений или приведения типов через type assertion. Это приводило к хрупкому коду: если ошибка оборачивалась в другую, исходная терялась.

Пакет errors решает три задачи:

  1. Создание ошибок - errors.New возвращает значение, реализующее интерфейс error. В отличие от fmt.Errorf, оно не содержит форматирования, но этого достаточно для простых случаев.

  2. Обёртывание ошибок - через fmt.Errorf с %w создаётся цепочка ошибок. errors.Unwrap позволяет достать предыдущую ошибку из цепочки. Это важно для сохранения контекста: вы можете добавить информацию о том, где произошла ошибка, не теряя исходную причину.

  3. Проверка ошибок - errors.Is сравнивает ошибку с целевой, проходя по всей цепочке через Unwrap. errors.As ищет в цепочке ошибку, приводимую к заданному типу, и записывает её в переменную.

Также пакет содержит errors.Join (Go 1.20) для объединения нескольких ошибок в одну, что полезно при валидации или параллельных операциях.

На практике

На собеседовании важно показать, что вы понимаете разницу между errors.Is и errors.As. Первая работает с значениями (sentinel errors), вторая - с типами. Sentinel errors - это предопределённые переменные, например io.EOF, sql.ErrNoRows. Их проверяют через errors.Is. Если ошибка несёт дополнительные данные (например, код HTTP-статуса), её оформляют как тип, реализующий error, и проверяют через errors.As.

Также стоит упомянуть, что errors.New создаёт ошибку с уникальным адресом: две ошибки с одинаковым текстом не равны по значению, поэтому для sentinel errors нужно использовать errors.Is, а не прямое сравнение.

Пример кода

GO
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("item not found")
type HTTPError struct {
Status int
Msg string
}
func (e *HTTPError) Error() string {
return fmt.Sprintf("HTTP %d: %s", e.Status, e.Msg)
}
func fetch(id int) error {
if id == 0 {
return fmt.Errorf("fetch: %w", ErrNotFound)
}
if id == 500 {
return &HTTPError{Status: 500, Msg: "internal error"}
}
return nil
}
func main() {
err := fetch(0)
if errors.Is(err, ErrNotFound) {
fmt.Println("not found")
}
err = fetch(500)
var httpErr *HTTPError
if errors.As(err, &httpErr) {
fmt.Println("status:", httpErr.Status)
}
// Unwrap вручную
unwrapped := errors.Unwrap(fmt.Errorf("wrap: %w", ErrNotFound))
fmt.Println(unwrapped == ErrNotFound) // true
}

Как отвечать на собеседовании

Начните с назначения пакета: создание, обёртывание и проверка ошибок. Затем перечислите ключевые функции и их сценарии. Обязательно приведите пример, где errors.Is и errors.As применяются в реальном коде. Подчеркните, что пакет появился в Go 1.13 и стал стандартом, заменив ручные проверки. Если спросят про errors.Join, упомяните его для агрегации ошибок. Говорите кратко, без лишней теории, но покажите, что понимаете цепочку ошибок и разницу между значением и типом.

Что проверяет интервьюер

Интервьюер оценивает:

  • знание базовых функций пакета и их назначения;
  • понимание разницы между errors.Is и errors.As;
  • умение работать с цепочками ошибок через %w и Unwrap;
  • знание sentinel errors и практик их использования;
  • способность объяснить, когда использовать errors.New, а когда fmt.Errorf.

Типичные ошибки

  • Сравнение ошибок через == вместо errors.Is - ломается при обёртывании.
  • Использование errors.As для проверки значения, а не типа.
  • Забывают, что errors.New создаёт уникальную ошибку, и пытаются сравнивать тексты.
  • Не используют %w в fmt.Errorf, теряя цепочку ошибок.
  • Путают errors.Is и errors.As местами.
  • Не проверяют, что errors.As записывает результат в указатель на тип, а не в сам тип.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью