Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Светофор качества Go-кода

Код, который неудобно читать, ломается не сразу: он сначала становится медленнее в разработке, а потом — дороже в поддержке. Проверять это на глаз неудобно, а линтер вроде golangci-lint требует установки и настройки. Здесь — быстрый разбор по эвристикам, которые замечает любой опытный ревьюер: размер функции, число аргументов, глубина вложенности, дубли и опасные вызовы.

оценка простоты 0–100разбор идёт в браузере

Что считает «хорошим» код в Go

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

Эвристики ниже — это те же правила, переведённые в проверки. Размер функции сравнивается с порогом в 40 и 80 строк. Количество аргументов — с четырьмя и шестью. Глубина вложенности — с тремя и четырьмя уровнями. Сверх этого ищутся длинные строки, повторяющиеся блоки, опасные вызовы (panic, log.Fatal, os.Exit, time.Sleep) и ошибки, которые присваиваются, но не проверяются.

Важно понимать границы: это не линтер и не замена go vet. Анализатор не знает вашего проекта, не понимает бизнес-логику и может ругаться на код, который в вашем случае уместен. Его задача — подсветить места, где стоит посмотреть глазами, и объяснить, почему это обычно плохо.

Вставьте Go-код

Анализ идёт прямо в браузере: код никуда не отправляется. Достаточно функции или фрагмента — например, обработчика запроса.

Примеры для проверки

Какие эвристики используются

  • Размер функции. Больше 40 строк — жёлтый, больше 80 — красный. Функция, которая делает несколько дел, трудно тестировать и переиспользовать.
  • Количество аргументов. Больше четырёх позиционных параметров — повод собрать их в структуру: иначе ошибку в порядке аргументов не поймает компилятор.
  • Глубина вложенности. Глубже трёх уровней — сигнал к раннему return или к выносу ветки в отдельную функцию.
  • Длинные строки и дублирование. Строки длиннее 140 символов и повторяющиеся блоки кода — источник неудобного чтения и расхождения копий.
  • Опасные вызовы. panic, log.Fatal, os.Exit, time.Sleep и присваивание в пустую переменную — типичные источники проблем в сервисном коде.

Это эвристики, а не линтер: они не знают контекста проекта и не знают, что делает код. Зато они работают мгновенно, без установки чего-либо, и подсказывают направление, в котором стоит копать. Для строгой проверки есть go vet и golangci-lint.

Частые вопросы о качестве кода в Go

Чем этот анализатор отличается от go vet и golangci-lint?

go vet проверяет корректность: неверные глаголы в Printf, потерянные копии мьютексов, подозрительные конструкции. golangci-lint собирает десятки линтеров и требует установки. Здесь работают эвристики читаемости: размер функции, число аргументов, вложенность, дублирование, длинные строки, опасные вызовы. Это другой класс замечаний — не «код неправильный», а «код будет трудно поддерживать».

Почему длинная функция — это проблема?

Функция длиннее 40-80 строк обычно делает несколько дел: читает, проверяет, преобразует, пишет. Такую функцию трудно покрыть тестами (нужно подготовить много входных данных ради одного результата), и при изменении требований легко сломать соседнюю ветку. Практическое правило: если функцию нельзя описать одним предложением без «и», стоит разбить.

Что делать с замечаниями про panic и log.Fatal?

В прикладном коде бизнес-ошибки возвращают через error — тогда вызывающий код может их обработать. panic оставляют для нарушенных инвариантов, которые восстановить нельзя, обычно при старте. log.Fatal и os.Exit в библиотечном коде особенно неприятны: процесс умирает без выполнения defer, и это ломает graceful shutdown у сервиса, который вызывающий код рассчитывал остановить сам.

Анализатор отправляет мой код на сервер?

Нет. Разбор идёт в браузере, код никуда не уходит и нигде не сохраняется. Страница статическая, внешних запросов на ней нет.

Что изучить дальше

Что внутри

Что именно проверяет анализатор

Пять групп сигналов: длина функции и число аргументов (функция с шестью аргументами почти всегда просит объект), глубина вложенности (условные ветки внутри условных веток), длинные строки и функции, дублирующиеся блоки, а также дорогие конструкции: panic и log.Fatal в серверном коде, потерянная ошибка, sleep вместо ожидания сигнала.

Каждое срабатывание объясняется: не «плохой код», а конкретное правило, которое в Go чаще нарушают, и как это выглядит в коде.

Сложность — не самоцель

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

Отдельно он смотрит на ошибки в обработке: вызов, который возвращает err, но результат используется без проверки, — это не стилистическая придирка, а способ потерять ошибку по дороге. Тот же смысл у panic и log.Fatal в серверном коде: они завершают процесс, и в воркере с очередью это означает потерю всех задач разом.

Что анализатор не ловит

Логические ошибки, неверную архитектуру, отсутствие тестов и проблемы в предметной области. Инструмент работает с формой кода, а не с его смыслом: он скажет, что функция делает слишком много, но не скажет, что она делает не то. Проверку «правильно ли это» делают тесты и ревью — автоматика берёт на себя только то, что можно посчитать.

Как пользоваться

  1. Вставьте одну функцию, а не файл. Анализатор показывает, что именно в этой функции подозрительно, и не комментирует соседей.
  2. Разбирайте срабатывания по порядку. Потерянная ошибка важнее длинной строки: сначала то, что ломает поведение, потом то, что мешает читать.
  3. Проверяйте себя на знакомом коде. Возьмите свой рабочий обработчик: если анализатор находит в нём десять проблем, а он у вас три года в проде, значит, правила слишком строгие — не чините код, смягчайте правила.

Когда это пригождается

Рефакторинг: с чего начать

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

Ревью чужого pull request

Список срабатываний — повод задать автору вопрос про конкретное место, а не спор о вкусе.

Тест не ловит баг

Если в функции шесть аргументов и три уровня вложенности, тест наверняка строит не те данные. Разбиение функции обычно чинит и тест.

Анализатор эвристический: он смотрит на форму кода, а не на смысл. Срабатывание — повод посмотреть, а не приговор.