Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to cook linters

How to cook linters

Iskander (Alex) Sharipov

April 13, 2019
Tweet

More Decks by Iskander (Alex) Sharipov

Other Decks in Programming

Transcript

  1. 1. Зачем нужны линтеры 2. 50+ линтеров: какие использовать 3.

    Запуск линтеров 4. Внедрение в проект 5. Удобство работы Содержание
  2. Почему линтеры не используют 1. Зачем нужны линтеры “Линтеры только

    замедляют разработку, и их долго настраивать”
  3. Почему линтеры не используют 1. Зачем нужны линтеры “Они находят

    только всякую мелочь, ничего серьезного”
  4. { Выводы Линтеры 1. Находить критичные баги 2. Находить баги

    рано 3. Ускорять код-ревью 4. Гарантировать качество кода 1. Зачем нужны линтеры
  5. Запуск нескольких линтеров 3. Как запускать линтеры pkgs = $(shell

    go list ./... | fgrep -v /vendor) lint: go get golang.org/x/lint/golint go get honnef.co/go/tools/cmd/staticcheck go get github.com/kisielk/errcheck golint $(pkgs) go vet $(pkgs) staticcheck $(pkgs) errcheck $(pkgs) Makefile для запуска 4-х линтеров
  6. Параллельный запуск 3. Как запускать линтеры pkgs = $(shell go

    list ./... | fgrep -v /vendor) lint: go get golang.org/x/lint/golint go get honnef.co/go/tools/cmd/staticcheck go get github.com/kisielk/errcheck echo $(pkgs) | xargs -P4 golint echo $(pkgs) | xargs -P4 go vet echo $(pkgs) | xargs -P4 staticcheck echo $(pkgs) | xargs -P4 errcheck
  7. Go Meta Linter 3. Как запускать линтеры $ gometalinter \

    --disable-all \ --enable golint --enable vet \ --enable staticcheck \ --enable errcheck \ --deadline=1m \ --vendor \ ./...
  8. Плюшки golangci-lint 3. Как запускать линтеры 1. Производительность 2. Удобная

    yaml конфигурация 3. Фильтрация предупреждений: --skip-dirs, --exclude 4. Исключения предупреждений в коде: //nolint
  9. Больше скорости. --fast 3. Как запускать линтеры $ golangci-lint help

    linters | fgrep "fast: false" 1. staticcheck 2. unused 3. gosimple 4. stylecheck 5. interfacer 6. unparam
  10. Больше скорости. Build cache 3. Как запускать линтеры $ go

    clean -cache $ time golangci-lint run --fast real 0m17.533s $ time golangci-lint run --fast real 0m6.585s
  11. Больше скорости. Build cache в CI 3. Как запускать линтеры

    # .travis.yml cache: directories: - $HOME/.cache/go-build - $HOME/gopath/pkg/mod
  12. Незначимые сообщения от линтеров 4. Внедрение в проект cache.go:7:6: exported

    type Cache should have comment or be unexported redis.go:13:6: exported type Redis should have comment or be unexported redis.go:17:1: exported function NewRedis should have comment or be unexported redis.go:33:1: exported method Redis.Get should have comment or be unexported redis.go:55:1: exported method Redis.Set should have comment or be unexported
  13. Исключаем неважные для нас сообщения 4. Внедрение в проект #

    .golangci.yml issues: exclude: - should have comment or be unexported - another pattern Опция `exclude` исключает сообщения по их тексту по регулярке golangci-lint автоматически находит .golangci.yml
  14. Исключаем по путям 4. Внедрение в проект # .golangci.yml run:

    skip-dirs: - pkg/examples skip-files: - ".*\\.generated\\.go$" golangci-lint автоматически исключает сгенерированны е файлы
  15. Исключаем конкретные случаи 4. Внедрение в проект var bad_name int

    //nolint:golint var b_a_d int //nolint:golint,gofmt var v int //nolint //nolint:prealloc func f() { // ... } Можно исключать текущую строку или блок //nolint
  16. Незначимые сообщения от линтеров 4. Внедрение в проект package logutils

    import ( "fmt" "os" "github.com/sirupsen/logrus" //nolint:depguard ) #https://github.com/golangci/golangci-lint/blob/master /pkg/logutils/stderr_log.go#L7
  17. Нет времени исправлять тонну проблем 4. Внедрение в проект $

    go vet main.go:5: missing argument for Sprintf("%s") main.go:6: missing argument for Sprintf("%s")
  18. Нет времени исправлять тонну проблем 4. Внедрение в проект $

    go vet main.go:5: missing argument for Sprintf("%s") main.go:6: missing argument for Sprintf("%s") $ go vet |& revgrep origin/master main.go:6: missing argument for Sprintf("%s")
  19. Нет времени исправлять тонну проблем 4. Внедрение в проект $

    golangci-lint run \ --new-from-rev=origin/master $ golangci-lint run --new
  20. Добавление нового линтера 4. Внедрение в проект $ golangci-lint run

    $ golangci-lint run \ --disable-all \ --enable newlinter --new-from-rev=origin/master
  21. Воспроизводимость в CI 5. Удобство работы go get github.com/some/linter wget

    -O - -q \ https://github.com/some/linter/install.sh | sh -s v1.2.3 golangci-lint run --enable-all golangci-lint run --disable-all -Eerrcheck -E...
  22. Pre-commit hook 5. Удобство работы # .pre-commit-config.yaml repos: - repo:

    https://github.com/golangci/golangci-lint rev: v1.16.0 hooks: - id: golangci-lint # pip install pre-commit # pre-commit install
  23. 1. Зачем нужны линтеры 2. 50+ линтеров: какие использовать 3.

    Запуск линтеров 4. Внедрение в проект 5. Удобство работы Что мы обсудили
  24. Кратко как применить доклад 1. Попробуйте включить все линтеры в

    golangci-lint 2. Встройте golangci-lint в CI + IDE + pre-commit 3. Примените --new-from-rev для быстрой интеграции 4. Сделайте линтеры ревьюерами через Reviewdog/CodeClimate.com/GolangCI.com/...
  25. Темы для дальнейшего обсуждения 1. Настройка .golangci.yml 2. Go/analysis и

    дальнейшее развитие линтеров 3. Разработка своего линтера 4. Страдания с gocyclo