Как стать автором
Обновить

Комментарии 18

Сколько лет народ ждёт generics, но, к счастью, этот ужас ещё не добрался до golang. И мы будем продолжать ждать.

В этот момент вспоминается фрагмент из замечательного фильма "6-е чувство":

— Я хочу открыть Вам свою тайну.
— Хорошо.
— Я вижу умерших людей...
— Во сне? Что, наяву? Они лежат в могилах? В гробах?
— Они везде ходят, как обычные люди. Они не видят друг друга. Они видят только то, что хотят. Они не знают, что умерли.
— Ты часто их видишь?
— Всё время. Они повсюду.

Забыли ещё цитаты про прекрасное решение - if err != nil { ... }. )

Да, в C#, например, можно запихнуть всё в один большой try … catch … блок и быть счастливым по этому поводу. При этом вся логика обработки ошибок будет жить в одном или нескольких catch блоках.

Пишу переодически на Go в прод, и понимаю что как хоршо когда ты все же можешь быть счастлив.))

Сколько лет народ ждёт generics, но, к счастью, этот ужас ещё не добрался до golang. И мы будем продолжать ждать.

Осталось ждать недолго, в марте новый релиз с ними обещают.

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

Основная проблема пакета errors в том, что вы не можете скрыть несколько частных ошибок за одной более абстрактной и проверить любую ошибку из цепочки (как с исключениями). За %w можно скрыть только одну ошибку. Т.е. правильным способом обработки ошибки из функции сейчас будет отлавливать огромную кучу мелких ошибок на самом низком уровне из каждой вложенной функции. Либо вы можете оставить только самую верхнюю ошибку с потерей предыдущего контекста.

Основная проблема пакета errors в том, что вы не можете скрыть несколько
частных ошибок за одной более абстрактной и проверить любую ошибку из
цепочки (как с исключениями).

https://pkg.go.dev/go.uber.org/multierr#section-readme

Остальные ищите тут: https://awesome-go.com/error-handling/

Покрытые тестами и используемые в проде многими крупными компаниями.

Хотел быть тем кто напишет про multierr)

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

Когда логируется ошибка мы видим что-то на подобие "ошибка при обработке такого то гет запроса: сервис вернул ошибку: база данных вернула ошибку: неожиданный символ в запросе на таком то месте, запрос такойто".

Имхо, удобно и прекрасно

Да, в C#, например, можно запихнуть всё в один большой try … catch … блок и быть счастливым по этому поводу. При этом вся логика обработки ошибок будет жить в одном или нескольких catch блоках.

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

Чем Ваш вариант с WriteError и проверкой if err != nil {return err} после каждой строки лучше try...catch?

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

Например, у меня в проде это дело стоит на всех обработчиках handler для возврата JSON, где этот JSON возвращается клиенту. Но «клиент» это air-gapped API.

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

сегодня дженерики, завтра exception-ы, классы и вот это вот все.
не хочется в эту сторону, go прекрасен. пожалуйста, остановитесь, не надо делать из него еще один c++ :)

НЛО прилетело и опубликовало эту надпись здесь

Я вот учу народ в Отусе. Преподаю C#, потому что я на нём писал последние 17 лет. Но сам пишу на Golang. Selection Statements превратили такую простую и незамороченную вещь как Switch Case в полный ужас. Хотя в тех же самых гайдлайнах по рефакторингу ООП написано, что если у вас используется большой и сложный Switch Case, то вам нужно переработать логику, скорее всего, вы где-то упустили классы. Логика не должна так работать.

В сам C# стали намешивать популярные фитчи из популярных языков (ну конечно, мы же берём пример с молодого, быстроразвивающегося и эффективного JavaScript). После этого в некоторых местах код начинает быть похожим на Perl.

Вот, скажите, нахрена нам нужно определять переменные при создании кейсов? Откуда берётся эта N? Кто её создаёт? Зачем?

switch (mark)
{
    case int n when n >= 80:
        Console.WriteLine("Grade is A");
        break;

    case int n when n >= 60:
        Console.WriteLine("Grade is B");
        break;

    case int n when n >= 40:
        Console.WriteLine("Grade is C");
        break;

    default:
        Console.WriteLine("Grade is D");
        break;
}

Всё это синтаксический сахар, без которого мы бы отлично прожили в C#. Потому что C# - это ООП. А в ООП про switch-case вообще говорят, что это "с запашком".

Что дальше? Мы все внезапно осознаем, что нам нужен goto? Потому что это единственный вариант выхода из трижды вложенных циклов?

Я уже не говорю по эту распаковку объектов в JS. Замечательно. У нас везде есть оператор ..., чтобы мы быстрее могли передавать ошибки из одного нетипизированного объекта в другой.

const { preserveWhiteSpace, noBreaks, ...restOfKeys } = config;

Выглядит замечательно. Потом когда начинаешь пользоваться, пытаешься выяснить, нахрена? Что мы делаем в этой строке? Мы создаём константу как? Мы что щас делаем?

А уже когда добираешься до современных React, где подлежащая система хранения стейта — это вопрос постоянного холивара на StackOverflow последние 5 лет. У тебя нет смысла чего-то учить. Всё-равно ведь потеряешь эти данные, потому что они падут жертвой очередного дуновения комментов. Я как-то в 2017 году сел и выучил Redux. Только чтобы узнать, что это уже бесполезная фитча.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Да, в C#, например, можно запихнуть всё в один большой try … catch … блок и быть счастливым по этому поводу. При этом вся логика обработки ошибок будет жить в одном или нескольких catch блоках.

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

лучше ли? если не пренебрегать обработкой ошибок, то половина строчек это


if err != nil {

Половина строчек это:

if err != nil {
  return ErrFooType("что-то пошло не так при вызове такой-то штуки", ERROR_FOO_SOME_CODE, err)
}

Или такой

if err != nil {
  logger.Warn("что-то произошло незначительное, но нужно знать", zap.Error(err))
}

Но чаще пишут так, что не очень хорошо:

if err != nil { return err }

Конструкцию if можно писать таким макаром:

if err := foo(); err != nil {
	return err
}

При этом err будет доступен только внутри фигурных скобок.

один из плюсов голанга — читаемость текстов. это всё слишком многословно и потому делает программу менее читаемой

Зарегистрируйтесь на Хабре, чтобы оставить комментарий