LINUX.ORG.RU

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

 , ,


0

3

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

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

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

★★★★★

Учи наизусть Go Proverbs https://go-proverbs.github.io и применяй буквально. Сказано «don't panic» — никогда не вызываешь panic, всё просто :).

Возможно, у тебя слишком большие функции. Как должна выглядеть идеальная функция:

func main() {
	app.Init()
	defer app.Close()
	err := app.Run()
	if err != nil {
		log.Fatal(err)
	}
}
hbee ★★★ ()
Ответ на: комментарий от hbee

Да, например: https://habr.com/ru/post/440008

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

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

И сама по себе проверка err != nil ничем не лучше чем except {}, поскольку она точно с такой же лёгкостью позволяет схалтурить на обработке ошибок путём их игнорирования или печати в лог, в результате чего получится ненадёжная программа.

Поэтому рекомендация «не паниковать» - это чисто стилевая рекомендация, которая для одних людей и случаев может подходить, а для других - нет. Я практически уверен, что авторы голанга никак не мотивируют свой приказ, поскольку «приказы не обсуждают». Но, чисто на всякий случай: почему нельзя паниковать?

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

Программа не должна падать в принципе.

Спасибо, но нет.

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

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

P.S. и да, я не буду учить то, что в меня пытаются вбить. Я хорошо понимаю смысл любой секты. Её смысл в том, чтобы промыть человеку мозг и что-то получить от него задаром. В голанге элементы секты (унаследованные от папаши Оберона) присутствуют вполне. Например, отсутствие возможности идентифицировать текущую горутину - это просто абсолютный нонсенс, также, как и отсутствие thread local storage. Я думал несколько дней, но так и не смог придумать этому какую-то уважительную причину, кроме виртовского стиля мышления, «отрезать всё, что не является жизненно необходимым». Но нужно понимать, что Вирт делал учебную ОС в одно лицо, и исходил из доступных ресурсов и дидактичности. А потом это обобщили на промышленные системы. Конечно, я буду обращать внимание на рекомендации авторов, но совершенно не собираюсь воспринимать их как руководство к действию :)

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

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

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

Вообще-то я хочу всюду использовать панику для обработки ошибок, как это делается в Java. Хотя вариант с «умными ошибками» имеет определённый смысл тоже, в тех местах, где я контролирую код.

Что делать с библиотеками - я пока не понимаю. Вероятно, можно определить класс ошибки и потом поставить брекпойнт на функцию error.New или её аналог. Поскольку error - это всего лишь интерфейс, задача «найти любое исключение» всё равно оказывается трудоёмкой, потому что я не могу запихнуть pkg/errors или аналоги в любой сторонний код.

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

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

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

Я как раз последние примерно полгода общался с первоисточником, т.е. конкретно с оберонщиками. oberoncore.ru и т.п. Многие из них просто принципиально не понимают. Секта может давать плюсы, и даже Оберон даёт плюсы. Но не всегда баланс плюсов и минусов будет в пользу прихожанина. Когда я впервые увидел Оберон, я предложил примерно тот же план изменений в него, который сделали авторы голанга. Сделать общий тип interface{}, сериализацию-десериализацию типов данных в текст, исключения, переменное число параметров. Вывод типов я не предлагал делать, это было на уровне дальних мечтаний, но я смотрю, как сделано в голанге и понимаю, что мечтания были довольно здравыми. Совпадение с голангом не 100%, но значительное. Так вот, каждый пункт, начиная от interface{} и заканчивая предложением создать нормальную IDE, встречал яростную критику большинства (хотя незазомбированные люди там тоже есть в некотором количестве). Можете почитать oberoncore :)

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

Но в продакшене — смерти подобно.

Опять же: почему? Почему на java и том же CL программы в продакшене прекрасно работают, невзирая на существование в них исключений?

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

Потому, что го нет исключений,

Можно по пунктам доказать, что паника - это исключения. Оставляю это тебе в качестве упражнения. Хотя я в голенге новичок, мог и ошибиться. В этом случае укажи мне, пожалуйста, на мою ошибку. Я уверен, так скажем, на 89%.

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

Я собираюсь попробовать в своих упражнениях максимально использовать панику

Для отладки прототипа норм. В боевом же коде такое может быть только от лени и рукожопия. Ни первое, ни второое, не могут служить оправданием.

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

В боевом же коде такое может быть только от лени и рукожопия.

Тебе тот же вопрос: чем паника функционально отличается от исключений и что не так с миллиардами строк кода на Java и C#?

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

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

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

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

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

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

Тема исключений очень объёмная, это отдельный срач на десятки страниц. Можно развести.

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

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

Библиотеки, которые ты будешь использовать, будут возвращать err, а в твоем коде будет наколхожены типо исключения из паники. Неконсистентно. Про работу в команде, я так понял, речи нет.

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

В общем, я уже предвижу, что я всё правильно понял и не упустил ничего из специфики исключений. И, что кроме социальных причин, больше никаких причин всегда предпочитать код ошибки исключениям, иных причин не существует. Что есть обходные пути, чтобы работать с кодами ошибки удобнее.

Важный вопрос - могу ли я поставить брекпойнт на конструкцию Struct{args} вообще, а не в конкретном месте - если да, то я смогу отловить ошибку за две итерации без всяких пакетов. Пока это предстоит выяснить.

Касаемо идентичности паники исключениям смотрим вот сюда:

https://stackoverflow.com/questions/3413389/panic-recover-in-go-v-s-try-catch...

Нужно прочитать все ответы, а не только первый.

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

Всегда следует стараться придерживаться принятых в рамках языка правил хорошего тона. Точка.

Ой, ребята it's a trap, лучше научится копать причину таких рекомендаций, а не тупо «придерживаться принятых практик».

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

Этого не достаточно? В рамках Go вопрос закрыт, я считаю. Тебе всё равно придётся иметь дело с обработкой ошибок из стандартной и сторонних библиотек.

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

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

То, что в сущности идентичны, это не вопрос. Вопрос в области применения.

Исключения ещё и в control flow используют, и как безобидные ворнинги, а в конкретно в Go паника — это не способ обработки ошибок, а способ элегантно свалиться в непредвиденной ситуации.

Плюс комментарием выше я уже привёл значимый технический аргумент (впрочем, его привели и без меня).

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

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

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

ибо исключения - зло.

Конечно зло, ведь без них намного удобнее.

func CopyFile(src, dst string) error {
    r, err := os.Open(src)
    if err != nil {
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }
    defer r.Close()

    w, err := os.Create(dst)
    if err != nil {
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }

    if _, err := io.Copy(w, r); err != nil {
        w.Close()
        os.Remove(dst)
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }

    if err := w.Close(); err != nil {
        os.Remove(dst)
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }
}
KillTheCat ★★★★★ ()
Ответ на: комментарий от WitcherGeralt

Что там обсуждать? Исключения - ошибка природы. Правильный способ обработки ошибок - явный возврат информации об ошибке вместе со значением. Как в сабже. Как в хаскеле, как в расте. Но. Каждый раз в ручную проверять код ошибки - удел пролетариев. Поэтому в хаскеле для обработки ошибок удобно приспособили ADT + монады. В Расте есть ADT, но нет монад, но сделали удобный оператор ? - получилось даже лучше. Но Go же рабоче-крестьянский язык, поэтому только пикрелейтед. Ничо, деды копипастили.

https://pbs.twimg.com/media/DCIF7-2W0AEAv9c.jpg

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

Исключения - ошибка природы.

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

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