TGViewer
Cross Join - канал о разработке Cross Join - канал о разработке @crossjoin · 3.82K subscribers
Post #346 3.68K
UPD: оформил в виде статьи на хабре

Ошибки в языке Go - это большая ошибка
=============================

Хочу явно прописать свои мысли, чтобы потом ссылаться на этот пост.

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

Но сорян, к бесконечным if err != nil я до конца привыкнуть так и не смог.

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

Читабельность

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

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

Возьмем самый-самый простой пример (псевдокод):

Вместо такого


прочитали из базы()
обработали()
записали результат()


Мы имеем


прочитали из базы()
if err != nil {
return fmt.Errorf("не смогли прочитать из базы: %w", err)
}
обработали()
if err != nil {
return fmt.Errorf("не смогли обработать: %w", err)
}
записали результат()
if err != nil {
return fmt.Errorf("не смогли записать результат: %w", err)
}


какой из двух кусков кода боле читабелен?

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

И это, знаете ли, big fucking deal. Как вы наверно знаете, при программировании люди тратят на чтение кода 80-90% времени, а на написание совсем чуть-чуть. Т.е. сначала надо разобраться, что уже происходит, и лишь потом добавлять новое. Так вот, с чтением кода в Go совсем беда. И беда эта связана только с обработкой ошибок, всё остальное в пределах нормы, а то и лучше.

Стек трейс

Стандартный пакет errors не сохраняет стек вызовов, поэтому когда вы в конце концов на самом высоком уровне получили ошибку и записали ее в лог, в логе вы просто так не поймёте, где изначально была проблема. Например, изначальная ошибка была "ошибка SQL запроса". Где sql, какой именно запрос из сотен? А трейс есть только на момент записи лога, остальной стек уже потерян. Именно поэтому люди вынуждены выкручиваться: использовать сторонние пакеты или прояснять ошибку вручную, добавляя информацию на каждом слое (через fmt.Errorf) или логировать прямо в месте ошибки (еще больше захламляя логику).

В общем, на практике вместо хотя бы

if err != nil {
return nil, err
}

чаще всего идет оборачивание

if err != nil {
return nil, fmt.Errorf("мы тут делали то-то и то-то, а нам вернули ошибку: %w", err)
}


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

Что делать?

Есть несколько десятков proposals, которые предлагают разные способы упрощения языка.

Например, ключевое слово try перед вызовом функции, которое работает практически как макрос, неявно добавляющий if err != nil {return nil, err}.

или так:
callSomeFunction() orfail
(в случае фейла идет возврат из функции с ошибкой)

тысячи их :)
Как по мне, надо сделать этот самый try. Но его недостаточно, потому что никто не возвращает просто ошибку, ее возвращают с пояснениями. Поэтому нужен try, запоминающий цепочку вызовов. И вот это уже будет бомба.
  • 👍 27
  • 👎 6
  • 🤔 4
  • 😁 2
  • 🌚 2
More from @crossjoin
  1. Sep 29, 2026😱 Отправили свое резюме на 129 вакансий на хх, а в ответ тишина .. Думаете, что дело в ры…
  2. Sep 28, 2026Слышал недавно в каком-то подкасте мысль, что Haskell плохо подходит для вайбкодинга прост…
  3. Sep 26, 2026Антон Жиянов написал мини-книгу по Go-concurrency. Это что-то вроде плотного конспекта с и…
  4. Sep 22, 2026photo post
  5. Sep 14, 2026Поможем Руслану собрать фидбек. Проект некоммерческий 👆
  6. Sep 14, 2026AGBX (Agent Box) — небольшой open-source CLI для запуска Claude Code и Codex в изолированн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →