В последнее (и не только последнее) время ломают много копий по поводу неудобства обработки ошибок в Go.
Суть претензий сводится к тому, что прямое использование:
customVar, err := call() if err != nil { doSomething(err) return err }
на больших количествах повторений гораздо менее удобно, чем классическое:
try { String customVar = call(); } catch (BadException e) { doSomething(e); sendException(); }
Можно долго спорить как по самому предмету претензий, так и по поводу обходных манёвров, однако же логика в «пакетном» подходе действительно имеется.
В связи с чем у меня и возникла мысль по поводу обработки исключений без особого отхода от «Go-way». Вариант не рабочий — всего лишь моя фантазия.
try err { customVar1, err := call1() customVar2, err := call2() customVar3, err := call3() } catch { doSomething(err) return err }
Общая идея такова: сразу после try объявляется переменная (в нашем случае err) типа error, область видимости которой — весь блок try…catch. Далее, при каждом присвоении переменной нового значения внутри блока try, компилятор проверяет его на nil, и если вернулась ошибка — следует переход в блок catch. Теоретически это не слишком затратная операция, производительность не должна пострадать.
Также возможно назначение нескольких переменных, типа:
try errIo, errNet { customVarIo1, errIo := callIo1() customVarIo2, errIo := callIo2() customVarNet1, errNet := callNet1() customVarNet2, errNet := callNet2() } catch { if errIo != nil { doSomething(errIo) return errIo } else { doSomething(errNet) return errNet } }
В данном случае пример не слишком наглядный, однако же при большом количестве кода внутри try бывает полезно сгруппировать ошибки, чтобы в catch их обработка не сводилась к:
switch err { case net.Error1: doSomethingWithNetError() case net.Error2: doSomethingWithNetError() case io.Error1: doSomethingWithIoError() case io.Error2: doSomethingWithIoError() }
В общем, у меня всё. Ругайте.
ссылка на оригинал статьи http://habrahabr.ru/post/270047/
Добавить комментарий