golangci-lint for Go: Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What is golangci-lint and why is it needed?

\n\n

golangci-lint is not just a library, but a powerful linter aggregator for the Go programming language. It is a single tool that runs many popular static code analyzers (linters) simultaneously, combining their results into one clear report. Essentially, it is a "linter of linters."

\n\n

Why is it needed? In modern Go development, maintaining code quality is a critical task. Disparate linters such as vet, staticcheck, errcheck, gocyclo, and dozens of others, each with their own flags and settings, can turn CI/CD configuration into a nightmare. golangci-lint solves this problem by providing:

\n
    \n
  • Single entry point: One command runs all configured linters.
  • \n
  • Parallel execution: Linters run in parallel, significantly speeding up the analysis process.
  • \n
  • Caching: Results are cached, making repeated runs (e.g., when only one file changes) nearly instantaneous.
  • \n
  • Flexible configuration: Easily enable/disable linters, configure their behavior via a YAML file or command-line arguments.
  • \n
  • Integration with IDE and CI/CD: Supported by most modern development environments (VS Code, GoLand) and continuous integration systems (GitHub Actions, GitLab CI, Jenkins).
  • \n
\n

Using golangci-lint helps teams automatically detect potential errors, stylistic issues, unused code, performance and security problems early in development, leading to more reliable and maintainable code.

\n\n

Installing golangci-lint

\n\n

Unlike regular Go libraries, golangci-lint is installed as a binary executable file, not imported into code. There are several installation methods:

\n\n

1. Quick installation (recommended for CI/CD)

\n

The simplest and preferred method is to use the installation script:

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

Note: Replace v1.59.1 with the current version from GitHub Releases.

\n\n

2. Installation via go install

\n

If you have Go version 1.21 or newer installed:

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

3. Installation via package managers (macOS/Linux)

\n

macOS (Homebrew):

\n
brew install golangci-lint
\n

Linux (Snap):

\n
sudo snap install golangci-lint --classic
\n\n

4. Verify installation

\n

After installation, verify that everything works:

\n
golangci-lint --version
\n

You should see something like: golangci-lint has version 1.59.1 built from ...

\n\n

Quick start with a code example

\n\n

Let's create a simple Go project and run golangci-lint on it.

\n\n

Step 1: Create the project

\n
mkdir my-lint-project\ncd my-lint-project\ngo mod init my-lint-project
\n\n

Step 2: Write "bad" code

\n

Create a file main.go:

\n
package main\n\nimport (\n    "fmt"\n    "io/ioutil" // deprecated\n    "log"\n)\n\nvar unusedGlobalVar = 42 // unused variable\n\nfunc main() {\n    x := 10 // unused variable\n    fmt.Println("Hello")\n    readFile("test.txt")\n}\n\nfunc readFile(path string) {\n    data, err := ioutil.ReadFile(path) // error is not handled\n    if err != nil {\n        log.Fatal                    

Recommendations