Go linters

Что: 617db3b1778e09fe4614cfea97d9dd3994b18e24

Когда: 2024-08-08 13:14:41+03:00

Темы: go python tip

Go linters

В Python я использовал много linter-ов. pep8, pycodestyle, mypy, pylint
и ещё какие-то. И многие из них приходилось настраивать, ибо что-то
сильно шумит, что-то я не считаю стоящим внимания, и т.д..

В Go же я просто использую staticcheck
(f1d82ecfdd6e17d41af5661a0dee479d7749293f). И нашёл я его когда искал
что-то, что могло бы сказать о deprecated вещах, которые я продолжаю
использовать, а также о ненужных "_" переменных.

Кроме него, у меня, собственно, gopls LSP сервер и Vim с ним работающий.
Вчера заметил, как он выдаёт предупреждение о логически не имеющим смысла
коде типа:
    if err != nil {
        ...
        if err != nil { }
    }

Я не понимаю как я годами программируя на Go, не задавался особо
вопросом linting-а. Я знаком с golint, помню его дикое количество
проверок и что там многое надо настраивать, чтобы уменьшить шум и
Google-specific предпочтения, поэтому для меня его запуск это какая-то
боль, которую я и не делаю. Видимо, это просто язык/компилятор так
хороши, что и без linter-ов можно жить.

Но LSP показал, что там много интересных онных. Но gopls не использует
чего-то хитрого или своего -- он просто переиспользует родные средства
из golang.org/x/tools/go/analysis. В нём включены почти все, но не все.

Среди крайне приятных и интересных оказался
golang.org/x/tools/go/analysis/passes/shadow, который показывает где
какая переменная "оттеняет" (err, как правило) предыдущее её
определение. Этого мне точно не хватало прежде! Я не раз допускал ошибки
из-за этого оттенения, в том числе в Си. Есть какая-то доля случаев,
когда это осознанный и явный шаг, ради удобства, но их мало. Поэтому в
идеале, даже если это ничему и не мешает, но всё же избавляться по
возможности от этого оттенения. /shadow чётко говорит на какой строке
кто кого оттеняет.

/fieldalignment анализатор говорит насколько компактнее можно сделать
поля в структуре. Безусловно я в курсе, как и в Си, о возможном padding
после полей, но в Go я редко задумываюсь об его оптимизации. Но нередко
не помешало бы. Причём, он не только может сообщить о возможной
оптимизации, но и самостоятельно выполнить её, чтобы не ломать голову. В
tools/go/analysis/passes/fieldalignment/cmd/fieldalignment можно собрать
команду, которой передать fieldalignment -fix ./....

Обожаю, что в Go нередко встречается подход как в suckless проектах,
как в моём web-сервере (bc087ee7e3be4177e83bc39ae3b1497e336ec5da),
встраивания настроек прямо в сам исходный код программы. При любом
изменении надо будет её перекомпилировать, да. Поэтому для штатных
(golang.org/x) linter-ов в Go нет какой-то программы с YAML/JSON/whatever
конфигурационным файлом. Всё делается очень просто:

    package main
    import (
        "golang.org/x/tools/go/analysis/unitchecker"
        "golang.org/x/tools/go/analysis/passes/appends"
        [...] -- десятки linter-ов
        "golang.org/x/tools/go/analysis/passes/usesgenerics"
    )
    func main() {
        unitchecker.Main(
            appends.Analyzer,
            [...]
            usesgenerics.Analyzer,
        )
    }

а дальше эта программа используется вместе с vet:
    go vet -vettool=/path/to/that/linter ./...

А ещё я в gopls увидел упоминание mvdan.cc/gofumpt утилиты для
форматирования кода. go fmt хорош. goimports, который я на самом деле и
использую -- ещё лучше, так как почти полностью заставляет забыть о
возне с добавлением/удалением import-ов. Но gofumpt полностью закрывает
все потребности перфекциониста. Например:
    var (
        foo = ...
    )
он преобразует в: var foo = ...
    var foo = ...
    var bar = ...
наоборот в:
    var (
        foo = ...
        bar = ...
    )
Добавит или удалить пустые строки между функциями, где go fmt ничего не
делает. "foo int, bar int" заменит на "foo, bar int". Даже закрывающие
скобочки может детерминированно подправить, как надо.

Или вот все Python программисты которых я видел -- так себе программисты
и поэтому у нас в Python экосистеме всё всегда было плачевно касательно
автоматического форматирования. То ли это просто Python такой дряной. Но
Go почему-то легко закрывает все хотелки моего внутреннего
перфекциониста. Даже в Си всё очень здорово с clang-format-ом, вообще
про форматирование не думаю, кроме как константных таблиц.

оставить комментарий

Сгенерирован: SGBlog 0.34.0