Почему mgo.DialWithInfo
возвращает не ошибку, а панику?
Я не знаю. Это может быть случай, что:
- вы делаете что-то неподдерживаемое, что вызывает панику в библиотечном вызове
- автор библиотеки решил использовать панику для сообщения о неисправимых ошибках
- в библиотеке есть внутренняя ошибка, которая вызывает панику во время выполнения при обнаружении неисправимой ситуации (например, разыменование нулевого указателя)
или их комбинация.
Ваш код не выглядит явно испорченным, хотя я не являюсь пользователем библиотеки mgo, и это не значит, что нет проблем с обменом данными с внешними ресурсами, которые невозможно диагностировать, посмотрев на код. Опубликуйте содержание сообщения о панике, которое может помочь нам точно определить, в чем проблема.
Почему не работает восстановление?
Это не ясно из вашего вопроса, но из вашего юнит-теста и этого комментария , похоже, восстановление работает , но не так, как вы предполагали, потому что оно не возвращает ошибка со значением паники.
Вызов recover()
в отложенном операторе восстановит управление программой паники, вернет значение, данное при инициировании паники, и возобновит нормальный поток выполнения. Это все, что recover
сделает. Это ничего не изменит с ошибками, если вы явно не напишите код для этого. (И, для полноты, без вызова recover
где-нибудь в отложенной функции в вашем стеке вызовов, паника в конечном итоге вспыхнет и станет фатальной для вашего приложения.)
В этом контексте работает паника: приложение не завершится смертельно, если паника возникает во время выполнения функции Connect
. Однако вы испытываете панику, не предпринимая никаких действий и не сообщая вызывающей стороне о том, что во время метода Connect
произошла ошибка.
Чтобы сообщить об этой ошибке, вы должны восстановить панику и выдать ошибку, которая может быть возвращена функцией Connect
. Вы не можете вернуть значение в отложенной функции напрямую, но вы можете использовать именованное возвращаемое значение для этого. Пример кода, пропускающий несущественные части тела функции:
func Connect(mongoDBDialInfo *mgo.DialInfo) (err error) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
// Return error from Connect with panic's value
err = fmt.Errorf("%v", r)
}
}()
// rest of function body
}