Так какие линтеры использовать?
2. Какие линтеры использовать
Slide 48
Slide 48 text
Каталог линтеров
2. Какие линтеры использовать
https://github.com/golangci/
awesome-go-linters
Slide 49
Slide 49 text
Запуск нескольких линтеров
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-х линтеров
Slide 50
Slide 50 text
Параллельный запуск
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
Slide 51
Slide 51 text
Go Meta Linter
3. Как запускать линтеры
$ gometalinter \
--disable-all \
--enable golint --enable vet \
--enable staticcheck \
--enable errcheck \
--deadline=1m \
--vendor \
./...
Slide 52
Slide 52 text
golangci-lint
3. Как запускать линтеры
$ golangci-lint run \
--disable-all \
-E golint,govet,staticcheck,errcheck
Slide 53
Slide 53 text
Сравнение производительности
3. Как запускать линтеры
Slide 54
Slide 54 text
Gometalinter
3. Как запускать линтеры
https://github.com/alecthomas/gometalinter/
issues/590
Конфигурация на примере goimports
3. Как запускать линтеры
import (
"github.com/local/repo/pkg"
"github.com/pkg/errors"
)
Slide 58
Slide 58 text
Конфигурация на примере goimports
3. Как запускать линтеры
import (
"github.com/pkg/errors"
"github.com/local/repo/pkg"
)
Slide 59
Slide 59 text
Авто-исправление
3. Как запускать линтеры
golangci-lint run --fix
Slide 60
Slide 60 text
Больше скорости. --fast
3. Как запускать линтеры
$ golangci-lint help linters | fgrep "fast: false"
1. staticcheck
2. unused
3. gosimple
4. stylecheck
5. interfacer
6. unparam
Slide 61
Slide 61 text
Больше скорости. --fast
3. Как запускать линтеры
$ time golangci-lint run
real 0m17.577s
$ time golangci-lint run --fast
real 0m6.757s
Slide 62
Slide 62 text
Больше скорости. Build cache
3. Как запускать линтеры
$ go clean -cache
$ time golangci-lint run --fast
real 0m17.533s
$ time golangci-lint run --fast
real 0m6.585s
Slide 63
Slide 63 text
Больше скорости. Build cache в CI
3. Как запускать линтеры
# .travis.yml
cache:
directories:
- $HOME/.cache/go-build
- $HOME/gopath/pkg/mod
Slide 64
Slide 64 text
go/analysis
3. Как запускать линтеры
https://godoc.org/golang.org/x/tools/
go/analysis
Slide 65
Slide 65 text
{
Выводы
golangci-lint
3. Как запускать линтеры
Slide 66
Slide 66 text
Незначимые сообщения от линтеров
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
Slide 67
Slide 67 text
Исключаем неважные для нас сообщения
4. Внедрение в проект
# .golangci.yml
issues:
exclude:
- should have comment
or be unexported
- another pattern
Опция `exclude` исключает сообщения по их тексту по регулярке
golangci-lint
автоматически
находит
.golangci.yml
Slide 68
Slide 68 text
Исключаем по путям
4. Внедрение в проект
# .golangci.yml
run:
skip-dirs:
- pkg/examples
skip-files:
- ".*\\.generated\\.go$"
golangci-lint
автоматически
исключает
сгенерированны
е файлы
Slide 69
Slide 69 text
Исключаем конкретные случаи
4. Внедрение в проект
var bad_name int //nolint:golint
var b_a_d int
//nolint:golint,gofmt
var v int //nolint
//nolint:prealloc
func f() {
// ...
}
Можно исключать текущую строку или блок
//nolint
Slide 70
Slide 70 text
Незначимые сообщения от линтеров
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
Slide 71
Slide 71 text
Нет времени исправлять тонну проблем
4. Внедрение в проект
$ go vet
main.go:5: missing argument for Sprintf("%s")
main.go:6: missing argument for Sprintf("%s")
Slide 72
Slide 72 text
Нет времени исправлять тонну проблем
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")
Slide 73
Slide 73 text
Нет времени исправлять тонну проблем
4. Внедрение в проект
$ golangci-lint run \
--new-from-rev=origin/master
$ golangci-lint run --new
Slide 74
Slide 74 text
Добавление нового линтера
4. Внедрение в проект
$ golangci-lint run
$
Slide 75
Slide 75 text
Добавление нового линтера
4. Внедрение в проект
$ golangci-lint run
$ golangci-lint run \
--disable-all \
--enable newlinter
--new-from-rev=origin/master
Slide 76
Slide 76 text
Воспроизводимость в 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...
1. Зачем нужны линтеры
2. 50+ линтеров: какие использовать
3. Запуск линтеров
4. Внедрение в проект
5. Удобство работы
Что мы обсудили
Slide 84
Slide 84 text
Кратко как применить доклад
1. Попробуйте включить все линтеры в
golangci-lint
2. Встройте golangci-lint в CI + IDE + pre-commit
3. Примените --new-from-rev для быстрой
интеграции
4. Сделайте линтеры ревьюерами через
Reviewdog/CodeClimate.com/GolangCI.com/...
Slide 85
Slide 85 text
Темы для дальнейшего обсуждения
1. Настройка .golangci.yml
2. Go/analysis и дальнейшее развитие линтеров
3. Разработка своего линтера
4. Страдания с gocyclo