НовостиОбзорыСобытияIT@WorkРеклама
ИТ-менеджмент:
Как модульный подход меняет разработку AI-агентов
Разнообразие low-code и no-code решений серьезно упростило создание IT-продуктов, в том числе, и на основе …
«Инструмент, без которого уже не пишут на Go»: интервью с автором golangci-lint Денисом Исаевым
При разработке на Go активно используются линтеры — программы для статического анализа кода. Металинтер golangci-lint …
Лучшие видеоредакторы для новичков и любителей
Начать монтаж видео сегодня довольно просто, т.к. любой видеоредактор работает по понятной логике «импорт — …
Почему выход новой версии ALD Pro — событие для российского рынка ИТ?
Мажорное обновление ALD Pro версии 3.0 — важный этап в развитии отечественных служб каталога. Релиз включает множество …
Дмитрий Кузьмин: «Архитектура — это поле, где решается будущее конкурентоспособности компании»
Архитектурные решения инженера-разработчика лежат в основе крупнейших коммерческих платформ, государственных сервисов …
 

«Инструмент, без которого уже не пишут на Go»: интервью с автором golangci-lint Денисом Исаевым

Юрий Николаев | 24.09.2025

При разработке на Go активно используются линтеры — программы для статического анализа кода. Металинтер golangci-lint позволяет запустить десятки линтеров одновременно, чтобы сократить время выполнения до нескольких секунд. Мы поговорили с создателем golangci-lint Денисом Исаевым — среди российских разработчиков он внес, возможно, самый большой вклад в экосистему Go (Golang). Денис рассказал, как родилась идея металинтера, и как golangci-lint за несколько лет превратился из личного pet-проекта в стандарт, которым пользуются тысячи команд по всему миру.

Денис Исаев

Денис, как вам пришла идея создать golangci-lint, и пересекался ли этот проект с вашими рабочими задачами на тот момент?

В 2017-2018 году я работал в Mail.Ru на проекте BeepCar в качестве Head of Backend and Frontend. BeepCar задумывался как онлайн-сервис по поиску попутчиков в автомобильные поездки. Бэкенд мы писали на языке программирования Go (Golang).

Цикл разработки устроен так, что сначала мы пишем код, а затем запускаем автоматические тесты, которые проверяют его корректность. Чтобы ускорить процесс проверки, после автотестов мы используем линтеры — программы-анализаторы, которые выявляют потенциальные ошибки, стилистические нарушения и другие недочеты.

На тот момент существовало около 20 линтеров, и они позволяли покрывать значительный класс ошибок в Go. Но их работа занимала на нашем проекте около 3 минут — это довольно значительное время, если необходимо провести несколько проверок за день. Уже тогда я начал думать над тем, как сократить это процесс — например, создать металинтер, который мог бы параллельно запускать все проверки.

Когда в 2018 году я устроился в Яндекс, у меня была пара свободных недель перед выходом на работу. И я решил, что успею реализовать свою идею. На тот момент в Яндексе не был распространен язык Go, и я создал golangci-lint просто из интереса, без какой-либо коммерческой выгоды.

Какие проблемы решал ваш металинтер в момент запуска, и изменилось ли это со временем?

Главной задачей было превратить 3 минуты проверки кода в 10 секунд. Так и получилось — а с развитием проекта скорость только нарастала. Через год после запуска металинтера он работал уже в 100 раз быстрее, чем исходное решение, а через пару лет удалось ускорить его еще в 3-5 раз.

Заслуга здесь не только моей идеи и команды open-source контрибьютеров, но и специалистов из core-команды самого языка Go. Увидев, с какими проблемами сталкиваются разработчики линтеров, они выпустили набор библиотек, стандартов и рекомендаций, с помощью которых можно было значительно ускорить работу.

Как устроена архитектура golangci-lint? Что позволило сделать его таким быстрым?

Я уже был знаком с проектом gometalinter, который запускает 20 линтеров параллельно. Я погрузился в его работу и понял, что примерно 90% действий каждого линтера дублируется: прочитать исходный код проекта, распарсить его, прогнать по нему базовый анализ и передать в логику конкретного линтера. И у меня появилась идея: сделать так, чтобы эти 90% работы делать только один раз.

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

Я вручную клонировал каждый из линтеров и изменил их исходный код, чтобы добавить интерфейс, который позволил бы работать только с отдельными этапами. И далее в своем golangci-lint я уже просто вызывал этот интерфейс. С помощью этих шагов я получил x10 к скорости.

Это было специфическое и довольно рискованное решение. На старте оно даже вызвало отторжение в сообществе. Чтобы объединить линтеры в свой golangci-lint мне пришлось клонировать каждый из них, и у других разработчиков появились опасения, что основная версия будет развиваться отдельно, а мой форк останется позади. При этом в каждый линтер я отправил pull request, чтобы разработчики забрали мои изменения к себе — но на практике половина из них не отреагировали.

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

Ваш проект стал по сути стандартом статического анализа кода в Go. Как вы думаете, в чем его главное преимущество перед другими линтерами, и почему именно он так широко распространился?

Ключевой особенностью проекта стала скорость — ни одно решение не позволяло так упростить и ускорить тестирование кода. Также golangci-lint очень приятен в использовании — своеобразный iPhone в мире open source. Немногие продукты с открытым кодом в то время могли таким похвастаться.

Чтобы достичь такого эффекта, я использовал более удобный формат конфигурации. В прошлом решении — gometalinter — применялся JSON-формат. Он более «машиночитаемый», но просматривать и редактировать его не так комфортно. Я перешел в своем решении на YAML, с которым человеку работать гораздо удобнее.

Также я написал подробную документацию и вложился в маркетинговый текст, где упомянул возможности, преимущества и недостатки моего решения по сравнению с конкурентами. Еще одним новшеством для мира open source стало демо — видеозапись, где я показал, как работает мой продукт. Сейчас многие разработчики тоже размещают демо на репозитории, но тогда это было редкостью.

В развитии продукта мне помогла обратная связь. Например, golangci-lint внедрили в работу мои бывшие коллеги из Mail.Ru Group. Они рассказали, что металинтер крайне сложно использовать в крупном проекте, который существует уже несколько лет. Если запустить линтер на всю кодовую базу, он покажет миллионы ошибок, накопленных за эти годы — и их исправление займет колоссальное количество времени.

Я придумал, как с этим справиться — нужно было научить металинтер запускать проверку кода только для внесенных изменений. Например, разработчик пишет код, меняя 1% кодовой базы — и только эту часть проверяет линтером. Мое усовершенствование помогло сделать golangci-lint еще более универсальным — чтобы его можно было применять на проектах любого объема.

Как golangci-lint повлиял на экосистему Go?

Прежде всего, мне хочется отметить, как он повлиял на саму команду разработки языка Go в Google — мы пообщались с ними на конференции GopherCon в 2019 году. Увидев golangci-lint, разработчики Go увидели проблему использования линтеров, с которой мне пришлось бороться — так появился стандарт интерфейса, который теперь используется во всех линтерах. Таким образом, я поспособстовал тому, чтобы облегчить работу всем разработчикам Go.

С 2019 года golangci-lint стал использоваться в большинстве новых проектов на Go — и это привело к двум следствиям. Во-первых, линтеров стало значительно больше — по умолчанию через golangci-lint запускается около 40-50. Если бы не существовало моего решения, то работа всех этих линтеров занимала бы 6-8 минут — это крайне долго. Возможно, из-за этого линтеры перестали бы создаваться, потому что никому не хотелось бы тратить столько времени на тестирование.

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

Когда вы начинали этот проект, то предполагали, что он будет развиваться таким образом? И что в нем происходит сейчас?

Было ожидание, что я решу проблему, которая заботит не только меня, но и коллег — и в целом сделаю интересный open-source продукт. Но я не думал, что он станет таким популярным, и его будут использовать почти все разработчики на Go.

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

Это освободило мне время для других важных проектов, но при этом я слежу за развитием golangci-lint и помогаю другим разработчикам. Сейчас среди участников проекта уже около тысячи специалистов, и сотни из них внесли важные усовершенствования.

Если бы вы запускали golangci-lint сегодня, что бы вы сделали иначе? Есть ли у вас уже идеи для следующего большого проекта — в области автоматизации кода или чего-то еще?

Мой подход к golangci-lint был чисто инженерным — проигнорировать то, как в сообществе принято работать со статическим анализом, и просто решать проблему. Первые два года такой подход работал, но позже я понял, что на этом далеко не уедешь. Проблема давно исследована, есть сотни научных статей на эту тему — и нужно изучить базовые понятия, чтобы работать не только над скоростью, но и над качеством анализа.

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

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

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

Другие спецпроекты
ПечатьПечать без изображений

Комментарии

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

Регистрация
Авторизация

ПОДГОТОВЛЕНО ITWEEK EXPERT

 
Интересно
12 ноября 2025 г. (среда), 10:00 — 18:30, Москва
Work 4.0: как меняется техническая кадровая политика в эру ИИ
Искусственный интеллект переносит рабочую силу в новую эру, которая меняет подход технологических руководителей …
Почему агентный ИИ нуждается в контекстном подходе
Ключ к раскрытию истинного потенциала искусственного интеллекта лежит в контекстной инженерии, выходящей за рамки …
Forrester: разработка ПО превращается из импровизации в полноценное оркестровое исполнение
Если разработка ПО — это музыка, то последнее десятилетие она была похода на джем-сейшен: разработчики …
ИИ — катализатор карьерного роста женщин в сфере технологий
Дополнительным преимуществом растущего интереса к генеративному искусственному интеллекту (GenAI) является то, что …
От сбора команды до постановки ТЗ: как банкам и аутсорс-разработчикам строить проекты в финтехе
Сегодня финтех-ландшафт меняется быстрее, чем большинство банков успевают обновлять свои ИТ-системы. Подключение к цифровому …