Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗goSpErAC 40 of 280 menu
◀ ▶

Достать тип ошибки в Go

Конкретный тип достают из ошибки, даже если она обернута в другую. Снаружи виден общий интерфейс error и один текст, а поля исходной структуры нужны для логики: путь, код, внутренняя причина. Для этого после проверки на nil используют команду из пакета errors, которая ищет тип в цепочке оберток.

Сначала посмотрим, как внешний текст сохраняет связь с исходной ошибкой через %w в fmt.Errorf:

package main import ( "errors" "fmt" ) type PathError struct { Path string Err error } func (e *PathError) Error() string { return e.Path + ": " + e.Err.Error() } func main() { inner := &PathError{ Path: "main.go", Err: errors.New("fail"), } wrapped := fmt.Errorf("read failed: %w", inner) fmt.Println(wrapped) }

Печать показывает и внешнюю фразу, и текст внутренней ошибки. Место %w⁆ в шаблоне кладет исходное значение внутрь новой обертки, чтобы позже можно было дойти до PathError. Команда errors.Is из основного курса сравнивает с готовым значением, а команда errors.As достает тип.

Достанем PathError из обернутой ошибки. Второй аргумент команды As это адрес переменной типа *PathError, без лишнего уровня указателя:

package main import ( "errors" "fmt" ) type PathError struct { Path string Err error } func (e *PathError) Error() string { return e.Path + ": " + e.Err.Error() } func main() { inner := &PathError{ Path: "main.go", Err: errors.New("fail"), } wrapped := fmt.Errorf("read failed: %w", inner) var pe *PathError if errors.As(wrapped, &pe) { fmt.Println(pe.Path) } }

На экране "main.go". Переменная pe получила указатель на исходную структуру. Если тип в цепочке не найден, условие ложно и pe остается nil.

Тот же прием работает, когда оберток несколько, пока внутри сохранена связь через %w:

package main import ( "errors" "fmt" ) type PathError struct { Path string Err error } func (e *PathError) Error() string { return e.Path + ": " + e.Err.Error() } func main() { inner := &PathError{ Path: "main.go", Err: errors.New("fail"), } mid := fmt.Errorf("layer: %w", inner) outer := fmt.Errorf("top: %w", mid) var pe *PathError if errors.As(outer, &pe) { fmt.Println(pe.Path) } }

Дана ошибка:

package main import ( "errors" "fmt" ) type PathError struct { Path string Err error } func (e *PathError) Error() string { return e.Path + ": " + e.Err.Error() } inner := &PathError{ Path: "main.go", Err: errors.New("fail"), } err := fmt.Errorf("open: %w", inner)

Запишите в path поле Path из PathError внутри err и выведите path.

Даны переменные:

package main import ( "errors" "fmt" ) type PathError struct { Path string Err error } func (e *PathError) Error() string { return e.Path + ": " + e.Err.Error() } pe := &PathError{ Path: "data.txt", Err: errors.New("denied"), } wrapped := fmt.Errorf("copy: %w", pe)

Проверьте, лежит ли в wrapped тип PathError, и выведите true или false.

Скажите, какой тип у второго аргумента команды As, если внутри нужен *PathError.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить