«Go»: обработка ошибок
После первого прочтения документации по языку «Гоу» у меня сложилось неправильное впечатление о конструкции «panic», отчасти
Моё небольшое исследование показало, что это не так, «panic» — это стандартное средство генерации ошибки (аналог исключений), тогда как «defer» плюс «recover» — стандартный способ сгенерированную ошибку отловить и обработать.
Напомню как это делается. Генерация ошибки осуществляется вызовом «panic», перехват —
Например:
package main
func test() int {
defer func() {
if e := recover(); e != nil {
print("Error\n")
}
panic(true)
}
func main() {
print(test())
}Ошибки могут быть типизированными: можно вызвать «panic(42)», «panic(„Hello“)», «panic(struct{h, k int}{0, 0})» или, к примеру, «panic(os.NewError(„Cannot open file“))», тип ошибки можно узнать, так же как и её содержимое. Это уже больше похоже на исключения.
Если внимательно посмотреть на мой пример выше, то не совсем ясно следующее: «паника» привёла к выполнению анонимной
Способ есть, давайте разберём его в другом примере. В нём же я покажу как именно определить тип «паники».
package main
import . "os" // содержимое модуля будет доступно без префикса
func poisson(n int) (result string) {
defer func() {
switch r := recover(); r.(type) {
case string:
result = "Result: " + r.(string) + "\n"
case Error:
result = "Error: " + r.(Error).String() + "\n"
}
}()
if n < 0 {
// NewError и Error используется из модуля «os»
panic(NewError("Poisson distributions have no value over negative numbers"))
}
panic("I dunno")
}
func main() {
print(poisson(-1)) // Poisson distributions have no value over negative numbers
print(poisson(+1)) // I dunno
}У функции «poisson», которая притворяется, что считает распределение Пуассона, возвращаемый параметр имеет имя, он как бы связан с переменной «result». Если мы
Что происодит дальше. Вызов «panic» принимает на вход «interface{}», то есть, фактически, параметр любого типа. Чтобы определить тип этого параметра, используется специальнуя конструкция «переменная.(type)» (которая, к слову, может использоваться только в операторе «switch»).
Упомянутая конструкция может определить какой тип ошибки нам вернулся. Похожая конструкция
Полученные значения обрабатываются и сохраняются в переменной «result», которая связана со значением возвращаемым функцией «test», оно и попадает в print функции «main».
Я уже настолько проникся языком, что это решение уже мне не кажется таким странным, как поначалу.
Комментарии 4
Области применения, минусы/плюсы, ссылки.