LINUX.ORG.RU

golang - не хочу возвращать err, хочу паниковать!

 , ,


0

3

Какая-то секта с этими err. Код распухает в несколько раз. Идея с defer выглядит довольно здравой - я в своё время делал такой defer для 1C и для Delphi. Но паника лучше, чем возврат err-ов. Таковой возврат ничего не упрощает. Когда выпадает исключение, сразу виден весь стек. Сгенерированный err не показывает места своего возникновения, т.е. с помощью брекпойнтов нужно много итераций, чтобы локализовать ошибку. А на fatalpanic есть чуть ли не встроенный брекпойнт, во всяком случае, у меня на fatalpanic отладка сама по себе останавливается.

Кроме того, разбор err после каждого вызова офигенно многословен, код распухает буквально в разы.

Я собираюсь попробовать в своих упражнениях максимально использовать панику. Труъ голангисты, разубедите!

★★★★★

Ответ на: комментарий от den73

Когда сервис при старте обнаруживает, что у него нет окружения например. Случай когда нет бд, приведённый выше, считаю невалидным, бд может в любой момент отвалится, её нужно ждать. А вот если речь была не про сервис, а про сценарий инициализации, то да. Он должен вальнуться.

WitcherGeralt ★★ ()
Ответ на: комментарий от den73

Скорее да, но если это сервис, то ему лучше не падать, а просто ничего не делать, попутно сообщая, что ему поплохело. Валиться нужно только тогда, когда продолжение работы не имеет смысла. Ну, либо грязный вариант, когда перезапуск теоретически решает проблему.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

А если я не знаю состояние программы, то где гарантия, что она будет продолжать отдавать 500, а не зависнет? «Будем надеяться, что не зависнет»?

den73 ★★★★★ ()
Ответ на: комментарий от WitcherGeralt

Да, я что-то не так спроектировал, но я же не бог, а человек. Имею право. И я хочу, чтобы если с помощью assert это выявилось, программа об этом внятно сообщала. Самый надёжный способ это узнать - это по коду возврата. Все остальные, вообще говоря, могут не сработать.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Паника — способ остановить конкретный кусок кода, который бессмысленно продолжать исполнять, а не обязательно вальнуться полностью. Веб-сервер же идеально иллюстрирует этот случай. Сам ведь привёл более-мене идиоматичный вариант, хоть и не осознал.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Я осознал то, что в этом подходе есть дефект. См. пример с FFI. Это вы не понимаете. Уже десятый раз одно и то же пытаюсь объяснить. На твоём языке получается, если сложить то, что вы говорите, то оказывается, что паники тоже нужно сортировать на «плохие» и «не очень». Если FFI поломало память, то надо падать, а если ошибка в логике, но затрагивает только часть веб-приложения и не приводит к разрушению инфраструктуры, не мешает продолжению других обработчиков, то нужно эту панику напечатать в лог и продолжить работу.

То же касается и ошибок. Если пришло err, то это не значит, что программа не должна упасть прямо сейчас по Os.exit(1)

Т.е. реакция на ошибку мало зависит от того, выражается ли эта ошибка как паника или как err. Вы не осилили пока что чётко сформулировать, что такое «ситуация, когда надо паниковать». Вы пытались дать какие-то определения, но они пока недостаточно чёткие.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Описанный случай с FFI это опять косяк архитектуры и вообще фейл, да ни в одном языке нет приёмов против unsafe-кода.

Т.е. реакция на ошибку мало зависит от того, выражается ли эта ошибка как паника или как err

Всё верно. Разница только в подходе к обработке. Паника нужна тогда, когда уже нет смысла продолжать выполнение конкретного участка кода и обрабатывать ошибку на месте. В идеале паниковать просто не следует. Но она есть для тех исключительных случаев, когда, например, очень не хочется рученьками проталкивать ошибку через весь стек, чтобы её потом куда-то тупо запринтить в том или ином виде.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 2)
Ответ на: комментарий от den73

Косяк в архитектуре в том, что такой код, который потенциально опасен, например, работает с FFI, нужно выделять в отдельный сервис, чтобы безопасно валить только его. Веб сервер валить не нужно.

feofan ★★★★★ ()
Ответ на: комментарий от den73

Но как валить этот сервер? А вот как: не с помощью паники, а с помощью os.Exit. Так что, как вы не прячтесь, но формула «для обычных ошибок - err, для необычных - паника» - не работает.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Ну, смотри, как проще всего (случайно) сломать программу из ffi так, чтобы это было необратимо и ничего не оставалось, кроме падения? Проще всего сломать внутреннее состояние объектов языка. Но от этого спасают высокоуровневые библиотеки. Если их не юзают, значит целенаправленно стреляют по ногам. Тут возникает вопрос, почему вообще до этого дошло? Это более чем просто программная ошибка, скорее всего виновато проектирование.

Ну, а вообще, я себе слабо представляю случай, когда ты что-то необратимо поломал и четко знаешь об этом. Обычно у тебя будут просто битые данные, либо всё и так скопытится и без ручного вызова паники.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Аргументация в направлении тезиса «использовать FFI - это ошибка проектирования» не принимается.

Но допустим, мы не авторы голанга с отмороженной головой и у нас есть проблемы с FFI. Прежде всего, мы наставим ассертов, которые вроде тут объявлены астрологией и чёрной магией.

Когда такой ассерт не прошёл, паниковать нет смысла, надо сразу вызывать exit(1). Если образ сломан, то даже это может не помочь, но паниковать со всеми defer-ами в сломанном образе точно не нужно.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Паника не для обычных или необычных ошибок, а особых случаев и разрабов, которые способны их определить. В общем случае никаких паник быть не должно. Don’t panic.

WitcherGeralt ★★ ()
Последнее исправление: WitcherGeralt (всего исправлений: 2)
Ответ на: комментарий от den73

Аргументация в направлении тезиса «использовать FFI - это ошибка проектирования»

Я этого не говорил. Я сказал, что высокоуровневые либы для ffi сами работают с представителями и не дают тебе палить себе по ногам. Но когда ты снимаешь предохранитель и всё равно палишь по ногам, то следует задуматься почему ты вообще это делаешь.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Так в каком «общем случае»? По твоей ссылке приведены конкретные примеры ситуаций, когда панику можно использовать, и для случая FFI там написана неправда.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Ты сказал:

Но от этого спасают высокоуровневые библиотеки. Если их не юзают, значит целенаправленно стреляют по ногам. Тут возникает вопрос, почему вообще до этого дошло? Это более чем просто программная ошибка, скорее всего виновато проектирование.

Что ты сказал, если не то, что использовать FFI - это ошибка проектирования? Не прямо сказал, но иного смысла я тут не вижу. Из этого никак не понятно, что делать, если мне самому нужно создать такую высокоуровневую библиотеку.

den73 ★★★★★ ()
Ответ на: комментарий от den73

а вообще, я себе слабо представляю случай, когда ты что-то необратимо поломал и четко знаешь об этом. Обычно у тебя будут просто битые данные, либо всё и так скопытится и без ручного вызова паники.

Паника тебе тут не пригодится, всё свалится прежде, чем станет ясно, что пора паниковать.

WitcherGeralt ★★ ()
Ответ на: комментарий от WitcherGeralt

Паника тебе тут не пригодится, всё свалится прежде,

Необязательно свалится, но паника не пригодится - это я согласен. Тогда в каких случаях её нужно применять на самом деле, что написано в святых книгах и написана ли там правда?

den73 ★★★★★ ()
Ответ на: комментарий от WitcherGeralt

Да нет, я просто взял то, что представляет из себя язык, добавил к этому опыт, и получилось совсем не то, что они там продвигают. Я не думаю, что я что-то подгонял.

den73 ★★★★★ ()
Ответ на: комментарий от den73

В приложении можно вызывать os.Exit в каких-то случаях, в библиотеке - нельзя. Деферы чаще всего должны выполняться даже при непрошедшем ассерте.

Всё таки почитай что такое graceful shutdown.

feofan ★★★★★ ()
Последнее исправление: feofan (всего исправлений: 1)
Ответ на: комментарий от feofan

Лисп в среднем примерно так же надёжен, чем голанг, и ломается примерно в тех же ситуациях. Ладно, когда-нибудь составим перечень ситуаций и для каждого я опрошу ъ гоферов, какая тут должна быть обработка. Но это будет чисто вопрос культуры.

Всё же ещё раз отмечу, что высказывания типа этого

GO does not have an exception mechanism you can't throw exceptions. During the execution when Go detects these mistakes, it panics

и

Go has no try/catch mechanism. The reason for this is simple: there is no exception.

которые повторяются в статьях как мантра - это ложь. В голанге исключения есть, но они названы по-другому. Это ложь в целях маркетинга, весьма обычная вещь. Например, такое же есть в Хаскеле, когда тайпклассы объявляются панацеей и нужно найти незазаобмированного программиста, который тебе скажет, что тайпклассы - это то же, что в других языках интерфейсы. Но она всегда бесит. Программирование близко к математике, а в математике не место такой грубой лжи и зомбированию.

Также очень плохой совет в effective go вот такой:

If the problem can be masked or worked around, it's always better to let things continue to run rather than taking down the whole program.

Такой подход растит проходимцев от инженерии. Я вижу его везде вокруг, но это не значит, что я с ним согласен.

И наконец, так и не достигнуто понимание гоферами того, что паника и возврат err - это два способа добиваться одного и того же результата, причём паника (исключения) - как правило, более удобна. А возврат ошибки в идиоматичном виде, когда возвращается просто error, который ни о чём - это плохая практика. Конструкция

if err != nil { 
  return
}
- ровно то же самое, что не обработка исключения в других языках, которая, в отличие от данной конструкции, занимает ноль строк.

По хорошему, если уж обрабатывать ошибки, то их нужно тщательно сортировать, и этот синтаксис (со switch) едва ли не многословнее блока except.

Т.е., вливаясь в ряды гоферов, я предвижу вот такие вот культурные проблемы, которые будут мне мешать работать в коллективе.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

В голанге исключения есть, но они названы по-другому.

И работают по-другому, угу.

Также очень плохой совет в effective go

Это же не библия, инженер должен видеть что к каким случаям подходит. А effective go больше для того, чтобы шибко умные новички не начинали творить всякую дичь. Я тебе уже кидал ссылки на стандартную библиотеку, где в некоторых случаях паника использовалась для обработки ошибок внутри глубоковложенных циклов.

Т.е., вливаясь в ряды гоферов, я предвижу вот такие вот культурные проблемы, которые будут мне мешать работать в коллективе.

И не зря. Но я вангую, что в твоем случае это не зависит от того, какой язык ты пытаешься переделать в лисп или паскаль.

feofan ★★★★★ ()
Ответ на: комментарий от den73

Это принцип «замети под коврик». В культуре, где каждый заботится только о своей жопе, он основополагающий. Клиент может и не заметить некорректную работу программы, а падение он уж точно заметит и не обрадуется, в результате имиджевые потери.

anonymous ()
Ответ на: комментарий от feofan

И работают по-другому, угу.

Ты это отказался обсуждать, а значит, и не будем обсуждать.

Но внезапно я обнаружил прямо сейчас случай, в котором могли бы быть полезны именно коды ошибок. А именно, в случае, когда ошибок может быть более одной. Например, я абстрагирую действие «открыть транзакцию, сделать в ней какую-то работу, описанную функцией fn. откатиться при ошибке, закоммитить при отсутствии ошибок». По идее я должен вернуть как ошибку из функции fn, так и ошибку самого коммита. Т.е. две ошибки. А исключения не может быть больше одного в данный момент времени.

Хотя я всё же сейчас не стану так делать, вместо этого я передам транзакцию в fn, пусть сама коммитит и обрабатывает ошибку коммита. Но в целом тут есть над чем подумать.

И тут же припомнил статью, где запускалось эн горутин и можно было получить массив из эн ошибок.

den73 ★★★★★ ()
Ответ на: комментарий от feofan

Вот, читаю:

https://jobs.zalando.com/tech/blog/hack-to-terminate-tcp-conn-postgres/?gh_sr...

Потому что возник вопрос, как будет вести себя сервер базы данных, если мой клиент грохнется. Как видишь, тут есть тонкости даже в системах, которые отлаживались десятилетиями. Соответственно, перед тем, как запустить свою программу в проде, я должен подстелить в этом месте соломки.

den73 ★★★★★ ()
Ответ на: комментарий от den73

Через год удивиться, что клиенты закончились.

Неее, это так не работает. Во-первых лохов много, во-вторых даже обманутые лохи возвращаются. Ты посмотри на микрософт: мы сделали XXX, который решит все ваши проблемы (дальше красочная презентация). Прошло пять лет, все говна наелись вроде бы, и тут: мы сделали YYY, который решит все проблемы XXX и еще увеличит ваш пенис вдобавок. И снова лохи валят косяком.

anonymous ()
Ответ на: комментарий от anonymous

Неее, это так не работает. Во-первых лохов много, во-вторых даже обманутые лохи возвращаются

К сожалению, ты прав. Я написал и сам сразу понял, что написал свои розовые мечты. Быть жуликом выгодно.

den73 ★★★★★ ()
Ответ на: комментарий от feofan

Такой код у меня бы тоже ревью не прошел

Ну я так и думал, что ты не пожелаешь увидеть, как это надо проэкстраполировать от упрощённого примера, в котором показана проблема в чистом виде, до реального варианта использования, где она будет закопана и возникнет случайно, так что в ревью ты сможешь её проглядеть.

Вот статейка про использование паники.

https://hackernoon.com/panic-like-a-pro-89044d5a2d35

Не сказать, что я её полностью прочитал, но там можно хотя бы в начале посмотреть статистику использования паники в известных гитхаб проектах.

Впрочем, тут можно напороться. Я вчера искал использование Log.Fatal и нашёл море, но это всё было в тестах.

den73 ★★★★★ ()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от dem

Кстати, реально заговор какой-то. Там даже биндинги к ncurses в зачаточном состоянии и заброшены. Где-то прочитал, что комьюнити мол не интересуется гуями. Это просто лол. Первое, что интересует программиста, решившего сделать что-то практически полезное, это гуи-библиотеки. На любом мейнстримном языке можно сделать гуи любой сложности, но только не на го.

anonymous ()
Ответ на: комментарий от anonymous

Это не заговор. Го поделие гугла. Он используется на серверах. Там GUI не нужен. Если кто то попробует скажем портировать wxWindows на Го, то это ваши проблемы. Оно вам надо? А главное в Го будут постоянно вносить изменения (что там с GOPATH)...

dem ()
Ответ на: комментарий от dem

Да любое комьюнити клепает биндинги к гуйне. Даже в каком-нибудь руби никаких проблем с этим нет. А тут языку 10 лет, и по большому счету голяк. Я вообще подозреваю, что нет там никакого комьюнити в привычном смысле. Как ни посмотришь на что-то за пределами стандартной либы, то просто слезы.

anonymous ()