golangci-lint для Go: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое golangci-lint и зачем он нужен?

golangci-lint — это не просто библиотека, а мощный агрегатор линтеров для языка программирования Go. Он представляет собой единый инструмент, который запускает множество популярных статических анализаторов кода (линтеров) одновременно, объединяя их результаты в один понятный отчёт. По сути, это «линтер линтеров».

Зачем он нужен? В современной разработке на Go поддержание качества кода — критически важная задача. Разрозненные линтеры, такие как vet, staticcheck, errcheck, gocyclo и десятки других, каждый со своими флагами и настройками, могут превратить настройку CI/CD в кошмар. golangci-lint решает эту проблему, предоставляя:

  • Единую точку входа: Одна команда запускает все настроенные линтеры.
  • Параллельный запуск: Линтеры запускаются параллельно, что значительно ускоряет процесс анализа.
  • Кэширование: Результаты кэшируются, что делает повторные запуски (например, при изменении только одного файла) практически мгновенными.
  • Гибкая конфигурация: Легко включать/отключать линтеры, настраивать их поведение через YAML-файл или аргументы командной строки.
  • Интеграция с IDE и CI/CD: Поддерживается большинством современных сред разработки (VS Code, GoLand) и систем непрерывной интеграции (GitHub Actions, GitLab CI, Jenkins).

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

Установка golangci-lint

В отличие от обычных Go-библиотек, golangci-lint устанавливается как бинарный исполняемый файл, а не импортируется в код. Существует несколько способов установки:

1. Быстрая установка (рекомендуется для CI/CD)

Самый простой и предпочтительный способ — использовать скрипт установки:

curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.59.1

Примечание: Замените v1.59.1 на актуальную версию с GitHub Releases.

2. Установка через go install

Если у вас установлен Go версии 1.21 или новее:

go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

3. Установка через менеджеры пакетов (macOS/Linux)

macOS (Homebrew):

brew install golangci-lint

Linux (Snap):

sudo snap install golangci-lint --classic

4. Проверка установки

После установки проверьте, что всё работает:

golangci-lint --version

Вы должны увидеть что-то вроде: golangci-lint has version 1.59.1 built from ...

Быстрый старт с примером кода

Давайте создадим простой Go-проект и запустим на нём golangci-lint.

Шаг 1: Создайте проект

mkdir my-lint-project
cd my-lint-project
go mod init my-lint-project

Шаг 2: Напишите "плохой" код

Создайте файл main.go:

package main

import (
    "fmt"
    "io/ioutil" // deprecated
    "log"
)

var unusedGlobalVar = 42 // неиспользуемая переменная

func main() {
    x := 10 // неиспользуемая переменная
    fmt.Println("Hello")
    readFile("test.txt")
}

func readFile(path string) {
    data, err := ioutil.ReadFile(path) // ошибка не обрабатывается
    if err != nil {
        log.Fatal(err)
    }
    _ = data
}

Шаг 3: Запустите линтер

golangci-lint run

Вы увидите вывод, подобный этому:

main.go:5:2: SA1019: "io/ioutil" has been deprecated since Go 1.16: As of Go 1.16, this package simply calls the corresponding functions in the "os" or "io" packages. (staticcheck)
main.go:10:2: `x` is unused (deadcode)
main.go:9:5: `unusedGlobalVar` is unused (deadcode)
main.go:15:21: Error return value is not checked (errcheck)

Всего одной командой мы нашли 4 проблемы! Теперь вы можете их исправить.

Основные методы/функции и команды golangci-lint

В отличие от обычной библиотеки, golangci-lint предоставляет функциональность через CLI-команды и YAML-конфигурацию. Рассмотрим основные из них.

1. Команда: run

Что делает: Основная команда для запуска линтеров. Анализирует код в текущем проекте и выводит найденные проблемы.

Параметры (основные):

  • --config или -c: Путь к файлу конфигурации (по умолчанию ищет .golangci.yml, .golangci.yaml, .golangci.toml).
  • --out-format: Формат вывода (colored-line-number, json, tab, checkstyle, html и др.).
  • --issues-exit-code: Код возврата при наличии проблем (по умолчанию 1).
  • --fast: Запускает только быстрые линтеры (обычно те, что не требуют полного AST-анализа).
  • --fix: Автоматически исправляет некоторые проблемы (например, форматирование, удаление неиспользуемого импорта).

Рабочий пример:

# Запуск с пользовательским конфигом и выводом в JSON
golangci-lint run -c myconfig.yml --out-format json

# Автоматическое исправление проблем
golangci-lint run --fix

# Запуск только быстрых линтеров
golangci-lint run --fast

2. Команда: linters

Что делает: Выводит список всех доступных линтеров с их описанием и статусом (включен/выключен по умолчанию).

Параметры:

  • --enabled: Показать только включенные линтеры.
  • --disabled: Показать только выключенные линтеры.

Рабочий пример:

# Показать все доступные линтеры
golangci-lint linters

# Показать только включенные по умолчанию
golangci-lint linters --enabled

3. Команда: config

Что делает: Позволяет управлять конфигурацией. С подкомандой path показывает путь к найденному конфигурационному файлу.

Параметры: Подкоманда path.

Рабочий пример:

# Показать путь к активному конфигурационному файлу
golangci-lint config path

4. Команда: version

Что делает: Выводит информацию о версии golangci-lint и используемых линтерах.

Параметры: Нет.

Рабочий пример:

golangci-lint version

5. Команда: help

Что делает: Выводит справочную информацию по командам.

Параметры: Название команды (необязательно).

Рабочий пример:

# Общая справка
golangci-lint help

# Справка по конкретной команде
golangci-lint help run

6. Директива конфигурации: linters-settings

Что делает: Позволяет тонко настроить поведение каждого линтера. Это не команда, а раздел в YAML-файле.

Параметры: Зависят от конкретного линтера. Например, для staticcheck можно задать checks, для gocyclo — min-complexity.

Рабочий пример (.golangci.yml):

linters-settings:
  gocyclo:
    min-complexity: 15 # Устанавливаем порог цикломатической сложности
  staticcheck:
    checks: ["all", "-SA1019"] # Включить все проверки staticcheck, кроме SA1019 (использование устаревших функций)
  errcheck:
    check-type-assertions: true # Проверять, что тип assertion обрабатывается

7. Директива конфигурации: linters

Что делает: Включает или отключает конкретные линтеры.

Параметры: enable, disable, presets.

Рабочий пример (.golangci.yml):

linters:
  enable:
    - errcheck
    - gosimple
    - govet
    - ineffassign
    - staticcheck
    - unused
    - gocyclo
    - gofmt
  disable:
    - deadcode # Устаревший, заменен на unused
  presets:
    - bugs
    - performance

8. Директива конфигурации: issues

Что делает: Позволяет исключать определённые проблемы из отчёта (например, по регулярному выражению, пути к файлу или тексту ошибки).

Параметры: exclude-rules, exclude-dirs, exclude-files, max-issues-per-linter.

Рабочий пример (.golangci.yml):

issues:
  exclude-rules:
    - path: _test\.go # Исключить все проблемы в тестовых файлах
      linters:
        - gocyclo
        - errcheck
    - text: "SA1019" # Исключить все предупреждения об устаревших функциях
  exclude-dirs:
    - vendor
    - third_party
  max-issues-per-linter: 0 # Не ограничивать количество проблем на линтер

9. Директива конфигурации: run

Что делает: Настройка времени выполнения, таймаутов и путей для анализа.

Параметры: timeout, tests, build-tags, skip-dirs.

Рабочий пример (.golangci.yml):

                
    
    

Рекомендаций