#go #testing #error-handling
# #Вперед #тестирование #обработка ошибок
Вопрос:
В go я часто использую
func MyFunc(s someInterface) error {
err := OtherFunc(s)
return fmt.Errorf("something wrong: %s", err)
}
Таким образом, я теряю исходное значение ошибки, потому что я просто беру строку ошибки и превращаю ее в новую ошибку. Это то, что я имею в виду под динамическими ошибками.
Теперь рассмотрим тест для MyFunc()
:
func TestMyFunc(t *testing.T) {
s := mockSomeInterface()
testErr := MyFunc(s)
if testErr != interfaceSpecificErrorValue {
t.Errorf("fail")
}
}
Для чего я буду использовать interfaceSpecificErrorValue
(что конкретно относится к someInterface
этому примеру)? Или как я мог бы сделать это проверяемым?
Я понимаю, что могу решить эту проблему, заранее определив все мои возможные ошибки и присвоив им постоянное значение. Меня интересует, есть ли другой способ добиться этого, потому что мне нравятся иерархические сообщения об ошибках, которые вы можете динамически создавать, используя fmt.Errorf("...: %s, err)
. Должен быть хороший способ сохранить иерархию ошибок без потери исходного значения.
(Сравнение выходных Error()
данных метода возможно, но не очень хорошо.)
Комментарии:
1. Может быть godoc.org/github.com/pkg/errors
2. Ошибки не обязательно должны быть строками. Стандартная библиотека полна типов ошибок, которые переносят другие, лежащие в основе ошибки ( os. Например , ошибка пути). Пакет, предлагаемый zerkms, быстр и прост в использовании, но я настоятельно рекомендую создавать конкретные полезные типы, которые позволяют обрабатывать ошибки, а не только сообщать о них.
3. @Peter не могли бы вы привести пример для конкретного, полезного типа? Я посмотрел на ОС. Ошибка пути, у него есть поле «Ошибка ошибки», содержащее ошибку «восходящий поток». Это то, что вы предлагаете?
4. ДА. Но у него также есть метод тайм-аута. На самом деле, многие типы делают это, и существует также общий временный метод . Они помогают вызывающим абонентам решить, стоит ли что-то повторять.
5. Разрешить обработку ошибок, а не только сообщать о них, — это тот намек, который мне был нужен. Хотя пакет, предложенный zerkms, безусловно, хорош для чтения, я не чувствую, что хочу добавлять это в свои проекты. Надеюсь, кто-нибудь добавит ответ с небольшим примером кода для хорошего, конкретного типа ошибки с контекстом, может быть, я придумаю что-нибудь позже.
Ответ №1:
Мой предварительный ответ на это таков: в Go в настоящее время нет канонического способа получения вложенных ошибок с сопоставимыми значениями ошибок.
После повторного прочтения официальных документов и сообщений в блогах об обработке ошибок, немного исходного кода из стандартных библиотек и, наконец, это предложение: https://github.com/golang/proposal/blob/master/design/go2draft-error-values-overview.md Поэтому я решил, что сохраню свои типы ошибок простыми и статичными и буду ждать, пока Go 2 предложит лучший способ.