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

Линтеры в Go. Как их готовить. Денис Исаев

Время на прочтение16 мин
Количество просмотров37K

Предлагаю ознакомиться с расшифровкой доклада Дениса Исаева jirfag "Линтеры в Go. Как их готовить."


В go 50+ линтеров: в чем их профит и как эффективно встроить их в процесс разработки? Доклад будет полезен как тем, кто еще не использует линтеры, так и тем, кто уже применяет их: я раскрою малоизвестные трюки и практики работы с линтерами.



Кому интересно, прошу под кат.


Привет. Меня зовут Деннис Исаев. Мы поговорим о том как готовить линтеры в Go. Доклад будет интересен как новичкам, кто еще не использовал линтеры, так и профессионалам. Я расскажу про некоторые малоизвестные трюки.



Немного об о мне. Я автор opensource проекта Golangci-lint. Работал в mail.ru. Сейчас работаю TeamLead в backend в Яндекс.Такси. Мой доклад основан на опыте общения с сотнями пользователей Golangci-lint. О том как они использовали линтер, какие у них были трудности и опыте внедрения Go линтеров в компаниях mail.ru и Яндекс.



Мы осветим 5 основных вопросов в докладе.



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



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



Кроме того, часто думают что линтер находит только мелочовку, что-то стилистическое, какие-то не критичные баги и на самом деле оно того не стоит. Проще ли тратить время.



Сразу контрпримеры. Баг в Docker найден с помощью go vet. Забытый вызов Cancel функции. Из-за этого фоновая горутина может не завершиться.



Баг в проекте Etcd. Классный линтер go-critic нашел что аргумент strings.HasPrefix перепутаны местами. Значит не будет работать проверка на небезопасный протокол HTTP.



В самом Go баг что i элемент сравнивается i-ым, хотя должен сравниваться с j-ым. Тоже найден линтерами.



Три примера в крупных opensource проектах найденные линтерами. Некоторые спросят: Ок и что? Он находит какие-то критичные баги. На один критичный баг находит 100 некритичных или ложных срабатываний. Могу привести свою эмпирическую статистику: у меня обычно где-то 80 процентов всех проблем которые репортят линтеры это: какие-то стилистические issues, например, переменные не используются и так далее, 15 процентов это реальные баги и где-то 5 процентов ложные срабатывания.



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



Часто бывает такое что на CodeReview разработчики репортят какие-то проблемы, которые могли бы найти линтеры. Зачем они это делают непонятно. Во-первых, автору кода нужно дождаться пока он пройдет CodeReview. Во-вторых, самому ревьюеру нужно потратить время чтобы найти какие-то механические проблемы. Он мог доверить это ли линтеру. Я когда такое замечаю всегда форсирую и мы договариваемся в команде что все что можно найти линтер, мы глазами не ищем на review. Мы доверяем все это линтерам. Более того, если мы находим какие-то проблемы которые в review часто бывают и линтеров на них нет мы стараемся найти линтеры, которые могли бы их в теории ловить. Чтобы мы не тратили время на review.



Линтеры позволяют нам как-то гарантировать и иметь предсказуемое качество кода в проекте. Например, в данном случае это неиспользуемые аргументы функции.



Линтеры позволяют находить критичные баги, максимально рано, экономить время CodeReview. При этом гарантировать какое-то качество кода по проекту.



В Go более 50 линтеров, но самые такие популярные 4. Это те, которые на слайде. Их использует просто потому что они классные. С остальными обычно не хочется разбираться. Я сейчас хочу на примерах показать какие вообще есть линтеры. Хочу продемонстрировать 25 линтеров на примерах. Сейчас будет наверное самое важное в докладе.



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



Также у gofmt есть малоизвестная опция -s, которая позволяет упрощать выражения.



Goimports содержит себе все то же самое что содержит gofmt, но дополнительно он еще умеет переупорядочить импорт, удалять и добавлять нужные импорты.



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



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



Nakedret это такой линтер, который умеет говорить что вы используете return без значений и при этом вы его используете в слишком длинной функции. По официальным guide такие return не рекомендуются.



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



Golint ругается на эту же переменную apiUrl. Говорит что url следует использовать большими буквами. Так как эта аббревиатура.



Gochecknoinits убеждается что вы не используете init функции. Init функции по определенным соображениям не следует использовать.



Gosimple классный линтер. Часть staticheck или megacheck. Внутри себя содержит огромное количество паттернов по упрощению кода. В данном случае можете заметить что strings.HasPrefix не нужен, так как strings.TrimPrefix уже содержит внутри себя нужные проверки и можно убрать if.



Goconst проверяет что у вас в коде нет повторяющихся строковых литералов, которые можно было бы вынести в константы. Количество этих повторов настраиваются. В данном случае два.



Misspell линтер, который проверяет что у вас в коде в комментариях нет опечаток. В данном случае на слайде опечатка слове else в тексте комментария. Можно настраивать диалект английского: американский, британский.



Unconvert линтер, который проверяет что вы не делайте лишние конверсии. В данном случае переменная уже типа string. Нет смысла ее конвертировать.



Теперь посмотрим линтеры, которые проверяют неиспользуемый код. Во-первых это varcheck. Он проверяет неиспользуемые переменные.



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



Deadcode говорит нам, если не используется тип.



Или не используется функция.



Unparam умеет сообщать когда аргументы функции не используются в самом теле функции.



Ineffassign репортит когда изменение переменой не используются дальше в коде. Это бывает либо результат какого-то рефакторинга. Где-то забыли что-то почистить, либо баг. В данном примере count увеличивается. При этом дальше никак не используется. Это очень похоже на баг.



Есть группа линтеров проверяющих производительность. Например, maligned говорит нам что данную структуру testStruck можно сжать в размере с помощью переупорядочивания полей. Более того, если запускать его как часть golangci-lint, у него есть опция позволяющая распечатать вам сразу нужный порядок полей, чтобы самому не подбирать их.



Есть такой классный линтер gocritic. Внутри у него множество проверок. Одна из них hugeParam. Она умеет репортить нам о копировании тяжелых структур данных. В данном случае heavyStruct копируется по значению и нам нужно просто передавать ее как указатель.



Prealloc умеет находить нам места в коде, в которых мы можем заранее преаллоцировать slice. Он это находит так, что ищет где мы делаем константные часовые итерации по slice. И в них дела append. В данном случае, можно сделать на длину slice ss преаллоцирование переменной ret и сэкономить память и ЦПУ.



И наконец линтеры, которые находят баги. Scopelint находит наверное самую часто ошибку новичков в go это захват переменной range цикла по ссылке. В данном случае переменная цикла arg захватывается по ссылке. На следующей итерации там будет уже другое значение.



Staticcheck. Раньше именовался megacheck. Теперь он переименовался. Из-за этого есть такая небольшая путаница в комьюнити. Staticcheck умеет находить тонны различных багов. Это совершенно классная штука. Как и go vet. Один из них на слайде — это гонка. Нам нужно конечно же инкрементить sync.WaitGroup до захода в горутину.



Go vet находит в основном баги. В данном случае переменная i сравнивается так что результат всегда будет true. Поэтому здесь очевидно баг. Вообще всегда стоит использовать go vet.



Gosec расшифровывается как go security. Находит потенциальные проблемы с безопасностью в Go. В данном случае у нас в arg могут поступать пользовательские данные. Поэтому она может проникать в shell команду rm. И тут может быть там shell in action например. Замечу что go security довольно часто выдает false positive. Поэтому я его иногда отключаю.



Errchek находит места где мы забыли проверку ошибок. Хорошим, безопасным стилем программирования считается везде всегда проверять все ошибки.



Отдельно должен отметить два линтера это staticcheck и go-critic. Потому что внутри себя каждый из них содержит еще по десятки, если не сотни, проверок. Поэтому обязательно посмотрите их попробуйте.



Сейчас мы рассмотрели 25 линтеров на примерах. И я еще говорил что у нас более 50 линтеров в Go. Какие использовать? Я советую обычно использовать все по максимуму. Включите просто все линтеры какие вы можете. А дальше потратьте час и начинайте их выключать по одному. Выключайте те которые вам кажутся несущественными. Например, он находит вам какие-то оптимизации производительности, которые вам вообще не интересны. Вы потратите час и сформируйте для себя свой список линтеров и с ним можете уже дальше жить.



Полный каталог всех линтеров есть по ссылке на слайде.



Поговорим про то как запускать линтеры. Иногда линтеры запускают с помощью таких вот makefile. Проблема в том что оно работает медленно. Оно все выполняется последовательно.



Мы можем сделать выполнение параллельно через xargs -P. Здесь тоже остается проблема. Во-первых, это всего лишь 4 линтера. А уже 10 строчек кода. Что будет если мы 20 линтеров включим. Во-вторых, это распараллеливание ну мягко говоря не самое оптимальное.



На помощь приходит gometalinter. Gometalinter это такой агрегатор линтеров, которые он может запускать буквально в пару команд. На слайде аналогичная предыдущему слайду команда запуска этих же линтеров. Но их не надо самостоятельно устанавливать и не нужно шаманить с параллельным запуском. Gometalinter уже под капотом все распараллеливает. Но у него есть одна фундаментальная проблема. Он запускает каждый линтер как отдельный процесс. Форкает его. Если добавить к этому знание о том что каждый линтер внутри себя 80 процентов времени тратит на парсинг кода и лишь 20 процентов на сам анализ, то получается что 80 процентов работы мы тратим впустую. И никак не переиспользуем данные. Мы могли бы 1 раз распарсить программу и дальше скормите 50 линтерам.



К счастью, есть golangci-lint, который делает ровно это. Он один раз парсит. Один раз достает типы. Дальше прогоняет на них уже анализаторы. За счет этого оно работает значительно быстрее. Аналогичная команда запуска на слайде.



Можно посмотреть график на одном из моих проектов 30 тысяч строк кода. Небольшой проект и всего 4 линтера. Можно заметить там колоссальную разницу по скорости работы в разы, как между последовательным запуском, так и между gometalinter, так и golangci-lint. Если этих линтеров будет не 4, а 20, то разница будет намного больше.



Важное уточнение про gometalinter. C 7 апреля автор проекта gometalinter объявив его deprecated. Репозиторий заархивировал и всем советуют переходить на golangci-lint, так как он более быстрый, там у него больше плюшек. Например, поддержка go модулей и так далее.



И кроме производительности и Go модулей в golangci-lint есть такие плюшки как YAML конфигурация, возможность как-то пропускать предупреждения, исключать их так далее.



Golangci-lint конфигурируется с помощью файла golangci-lint.yaml. Пример этого файла с описанием всех опций есть по ссылке на слайде. Рассмотрим, например, секцию linters-settings. В этой секции рассмотрим конфигурацию goimports. У него есть такая редкая опция local-prefixes. В ней можно указать путь к текущему проекту. В данном случае для примера github.com/local/repo.



Когда goimports будет видеть локальные импорты и в github.com/local/repo, он будет обращать внимание на то чтобы они были в отдельной секции.



Чтобы они были в самом конце. Чтобы они были отдельны от всех внешних импортов. Это позволяет просто визуально удобнее отличать внешние от внутренних импортов. Если он заметит что это не так, то он будет ругаться.



А если вы еще и используйте опцию golangci-lint run --fix, то golangci-lint еще и зафиксит за вас автоматом и пересортируют импорты.



Поговорим про то какие есть линтеры есть в терминологии golangci-lint. Линтеры делятся на быстрые и медленные. Быстрые называются fast, помечены флажком fast в help. Отличаются они тем что быстрые линтеры требуют довольно ограниченное представление программы, например AST дерево и какую-то информацию о типах. В то время как медные линтеры еще дополнительно требует SSA представления программой и меньше переиспользуют кэш. Медленных линтеров всего шесть. Они помечены на слайде. Есть определенные кейсы, когда имеет смысл запускать только быстрые линтеры.



Можно заметить разницу в скорости. Она колоссальная в три раза между быстрым запуском и медленным. Собственно golangci-lint run --fast запускается только быстрые линтеры.



Про build cache. Есть такая штука как build cache. Это кэш, который строится бинарником Go при компилировании программы при загрузке типов, чтобы следующий раз эта компиляция была быстрее. Этот же кеш переиспользуют линтеры для парсинга программы для построений информации о типах. Можно заметить что если кеш очистить, то первый свежий запуск будет довольно долгим. А последующий будет уже в 3 раза быстрее. Обратите внимание на ваш первый запуск линтеров на вашем проекте. Он всегда будет значительно медленнее.



Здесь же можно сделать вывод что есть смысл в CI между запусками CI переиспользовать ваш кэш. Вы ускорите не только линтеры, вы ускорите еще и запуск тестов, просто компиляцию и возможно ещё что-то. Всем советую.



Не могу не поговорить про go analysis. Это новый фреймворк, который появился начиная с Go 1.12. Он унифицирует интерфейсы таким образом что линтеры становится легко писать, линтеры легко использовать, запускать. Go vet начинается 1.12 вообще перешел целиком на go analysis. Очевидно что за этим будущее. Что оно сильно изменит всю экосистему Go. Но пока вообще довольно рано говорить об этом. Чтобы что будет дальше? Потому что я видел всего несколько линтеров на go analysis и практически ни один из существующих на него еще не перешел.



Если сделать краткий вывод по секции как запускать линтеры, то советую всем использовать golangci-lint. Вы будете быстро удобно запускать линтеры. Вам не надо шаманить с другими инструкциями, командами.



Поговорим про то как внедрять линтеры в проект. Я думаю там все кто пытались внедрить линтеры сталкивались с такой проблемой. Вот у вас проект на миллион строк кода с историей. Вы убедили TeamLead внедрить линтеры. Запускаете и видите миллион сообщений. Понимаете что вам сидеть безвылазно недели чтобы все это исправить. Что делать? Можно просто сдаться и бросить все это. Или можно что-нибудь придумать.



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



Можно исключить путям. Например, у вас есть директория third-party и там лежит не ваш код. Вам его не нужно проверять. Можно исключить по именам файлов.



Если вы не хотите исключать целиком весь файл, вы можете исключить функцию с помощью nolint перед функцией. У nolint можно указать через двоеточие список линтеров, для которых оно действует как исключение. Либо не указывать, тогда будет игнорировать все линтеры.



Когда вообще использовать nolint? Например, я использую nolint:deepguard, который умеет заблеклистить импорты, т.е. импорты нельзя использовать. Я заблеклистил импорт библиотеки logrus для того чтобы случайно не использовать его вместо моего нужного логера. Но в самом моем логере я использую logrus. Поэтому мне нужно только в одном месте в проекте только в одном файле сделать от импорт. Я помечаю его с помощью nolint.



Допустим вы все это сделали, exclude добавили, nolint проставили. Видим что все равно осталось тысячи сообщений. Исправлять это несколько дней. Есть классный хак. Рассмотрим на примере. Есть файлик main.go, в котором 5 строчка добавлена давно, а 6 строчка добавлена только сегодня. Что можем сделать?



Мы можем использовать revgrep. Revgrep позволяет нам указать git ревизию, после которой нужно искать баги. То есть оставлять сообщение линтеров только после заданной ревизии. Если 6 строчка у нас изменена после origin master, то он за зарепорит только ее. А все предыдущие сообщения, 5 строчку он не зарепортит. Это очень классный трюк. Именно с помощью него можно внедрить линтер любой проект за час. Как мы это делаем. Мы берем запускаем там golangci-lint на проекте в миллион строк кода. Он выдает тысячу предупреждений. Мы немножко понастроили, подшаманили. Дальше мы договариваемся с командой что прямо сейчас мы делаем git ревизию или используем hash commit. После которого мы не допускаем ошибки линтеров. Но до которого мы все ошибки линтеров оставляем и пока их не правим или правим медленно. Мы указываем это этот hash commit или tag в revgrep и начинаем запускать CI. Отныне линтер будут репортить нам только ошибки в новом коде. При этом старом коде они никак не будут реагировать на ошибки. и таким образом можно вот реально за час внедрить линтеры в любой проект. Именно так я сделал в mail.ru, когда внедрял линтеры в огромные проекты.



Более того revgrep уже внедрен в golangci-lint. Достаточно просто указать опцию --new-from-rev или --new. Всем обязательно советую.



Здесь есть еще одна тонкость. Допустим мы постепенно со временем все ошибки зафиксили в старом коде и убрали вообще опцию --new. У нас сейчас есть 20 линтеров, мы их запускаем. Новых ошибок нет. В один момент добавляется новый линтер. Мы хотим этот линтер тоже запускать. Но он выдает очень много ошибок. Что делать? Если мы добавим --new-from на все линтеры, то будет не круто. Мы хотим все прошлые линтеры запускать на всем проекте.



Решение простое. Можем запускать golangci-lint дважды. Один раз запускать его на новом коде с новым линтером. Второй раз запускать его целиком со всеми старыми линтерами на всем проекте. Такой трюк сильно помогает внедрять новые линтеры, когда они выходят.



Мы поговорили про внедрение линтеров в любой проект. Теперь поговорим про удобство работы. Во-первых, нужно добиться воспроизводимости в CI. Как только вы добавляете линтер в CI, вам нужно чтобы она была стабильна. Никогда не делайте go get. Потому что оно не версионировано. Линтер в любой момент изменился, обновился и у вас все CI build начали фейлиться. Это я видел десятки раз. Всегда используйте конкретные версии. Лучше с помощью wget ее поставьте. Она еще быстрее будет. Кроме того, не рекомендую использовать опцию ---enable-all для линтеров, потому что в один день вы обновляете golangci-lint, например, у вас добавляется 5 новых линтеров и у вас все build начинает фейлиться. Потому что вы эти линтеры случайно включили. Лучше явно прописываете какие линтеры включаете.



Классная штука pre-commit hook. Кто использует pre-commit hook поднимите руки? Довольно мало. Pre-commit hook это файл в git, который позволяет вам исполнять произвольный код после того как вы захотели закоммитить. Но до того как этот commit завершится успешно. Если pre-commit hook возвращает вам ошибку, to commit не пройдет. Туда обычно удобно встраивать быстрые тесты, статический анализ и так далее. Всем советую встраивать golangci-lint. Можно делать это вручную через shell скрипт. Можно через утилиту pre-commit. Пример того как настроить на слайде. Устанавливается pre-commit с помощью pip — утилиты для установки пакетов Python. pip install pre-commit устанавливает конфиг. Golangci-lint уже поддерживает интеграцию с pre-commit.



Опция --fast. Мы к ней вернулись. Всем советую использовать в IDE именно ее. Вообще в IDE конечно же стоит использовать интеграцию с линтерами. Для того чтобы ваша IDE не подвисала обязательно используйте опцию --fast.



Думаю это довольно очевидно. В CI линтеры надо встраивать. Если вы их не встроите, то будет классическая картина: "давай сейчас забьем, сейчас у нас релиз, не до этого". Постепенно у вас будет все больше и больше замечаний. Вы просто перестанете смотреть на линтеры как класс. Поэтому строго в CI. Более того, можно просто установить линтеры в CI, при build fail мы залезаем в build log, ищем почему он там свалился. Где какое замечание, на какой строчке? Это не очень удобно.



Есть способ круче. Можно сделать так чтобы линтеры выступали как человек, как reviewer. Они могут комментировать вам в github.com, gitlab.com строчки кода с ошибкой на вашем Pull request. Линтер могут писать что нашёл проблему. Это невероятно круто. Это позволяет экономить время авторов кода. Потому что не нужно лезть в build log. Плюс человек может прокомментировать, если он не согласен с этим замечанием линтера. В примере на слайде это делается с помощью утилиты reviewdog. Утилита opensource. Она бесплатная. Можно у себя установить.



Кроме reviewdog есть еще такие проекты как GolangCI, Code Climate, Hound. Они позволяют подключить буквально в один клик к своим opensouce или приватным репозиториям вот эти вот линтеры и комментировать inline в Pull Request. Есть еще классная штука SonarQube.



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



Я хотел бы чтобы вы прямо в понедельник пришли на работу и смогли что-то применить из того что я сказал. Вот кратко что можно применить. Во-первых установите golangci-lint. Включаете там все линтеры. Дальше тратите 1 час. За этот час выключаете все линтеры, которые вам кажутся бредовыми. После этого встраиваете golangci-lint в CI, в IDE и настраивайте pre-commit hook. Cразу после этого можно настроить --new-from-rev и указать что с текущего коммита мы ищем баги. А все предыдущие баги будем исправлять потом отдельно. После этого опционально настраиваете reviewdog, чтобы он еще комментировал вам в ваш github или в gitlab. Вы повысите этим качество проекта просто колоссально. Обрадуете всю команду.



Всем спасибо за внимание. Мои контакты на слайде.


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


Ответ: Хорошая идея. В самом golangci-lint уже есть свой golangci-lint.yaml, который он использует. Можно его использовать как стартовую точку.


Вопрос: На слайде про build cache ссылаешься на кэш для модулей. В кэше указываешь полностью кэш модулей. Можно указать .cache/downloads тогда будет достаточно большое различие: 400 мегабайт против 10. Этого достаточно для того чтобы модули просто экстрактились. Но это только если модуль используется.


Вопрос: Будете также поддерживать и go модули или dep или уходить во что-то в одно?


Ответ: Не нужно одно поддерживает. Сейчас есть библиотечка go packages. Она занимается подгрузкой исходного кода. Она поддерживает и модули и не модули. Она не собирается пока но убирать поддержку не модулей.


Вопрос: Планируете ли вы делать различные плагины для интеграции с не только с Travis, но и с другими серверами автоматизации?


Ответ: golangci-lint не делает никакой интеграции. Чтобы в CI запустить достаточно просто вызвать golangci-lint --run.


Вопрос: Чтобы парсить какие-нибудь репорты, например в дженкинсе мы сохраняем html-файл.


Ответ: Есть формат вывода junit, csv, json xml. Это все уже можно парсить.


Вопрос: мы использовали раньше gometalinter и он был медленный. Потом мы переключились на линтер кто называется revive. Вы его вообще никак не упоминали. А я с моей стороны я вообще не эксперт в теме. Я не знал про ваш линтер, который вы рассказывали. Вы не могли бы в конце писать допустим плюсы вашего линтера или плюсы revive.


Ответ: revive это переписанный golint. Это всего лишь один из линтеров. Там есть настройки. Он еще добавил несколько линтеров, несколько проверок. Golangci-lint это внутри себя 30-50 линтеров. Это в revive полтора линтера. Revive классен тем что он взял golint и сделал параллельным. Revive работой быстрее чем golint. Но это лишь один линтер. Revive можно сделать частью golangci-lint.


Вопрос: У тебя был слайд в обзоре линтеров про gocritic: hugeParam, который рекомендуют передавать жирные структуры по указателю. Но это же приведет к тому что все эти структуры будут аллоцироваться исключительно в HEAP. И не приведет ли это к большим проблемам, чем преимуществам? Если таких структур, например, передается много.


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


Вопрос: Я из Яндекса. Мы пользуемся вашим линтером на большом репозитории. Заметили что он большом репозитории уже начинает не очень быстро работать. Буквально за пару дней написали простую утилиту, которая через go package находит пакеты, которые изменились с момента введения ветки от мастера и пакеты, которые от них зависят. И запускаем линтер только на них. И проверка линтером в разы ускорилась.


Ответ: Может быть вы idssue создадите, приложите скриптик и вполне возможно я все это встрою в golangci-lint.


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


Ответ: Много человек просило и сразу скажу сложность том, что вот эти уровни серьезность их поддерживать всего там 3 или 4 линтера из с 30. Что делать со стальными? Не понятно. Нужно получаться в ручную парсить их замечания, как-то размечать их. Обрабатывать ложные срабатывания. Это вообще большой объем работ. Я не уверен что это когда ли будет сделано. Есть другие способы как достичь той же самой цели.


Вопрос: На хабре есть статьи. А точнее серия статей про C++ линтер. Компания развивает это дело. Они зарабатывают на этом деньги. На самом деле их работа, а точнее эта серия публикаций направлена больше не на разработчиков, а больше на тех кто разработчиками управляет. Эта по сути чистота кода, стилизация. Это наша задача, но и задача руководителей, тимлидов. Планируется ли вот популяризация вот этого направления, линтеров в СМИ, в крупных таких ресурсах, чтобы люди это читали и потом это внедряли своих командах? А не мы снизу стучались.


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

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 19: ↑18 и ↓1+17
Комментарии4

Публикации

Истории

Работа

Ближайшие события