golangci-lint 支持并行运行 lint、缓存、YAML 配置,且支持与主流集成开发环境集成,并包含一百多个 lint 程序
介绍
- 非常快:并行运行筛选器,重用 Go 构建缓存并缓存分析结果
- 基于 YAML 的配置
- 与 VS Code、Sublime Text、GoLand、GNU Emacs、Vim 和 GitHub Actions 集成
- 内置大量 linters,无需安装
- 内置默认设置,误报率最低
- 带有颜色、源代码行和标记标识符的漂亮输出
安装
# bin
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.59.1
golangci-lint --version
# mac
brew install golangci-lint
brew upgrade golangci-lint
# Linux
直接到 https://github.com/golangci/golangci-lint/releases 下载二进制包
# go
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1
# Docker
docker run -t --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.59.1 golangci-lint run -v
help
$ golangci-lint --help
Smart, fast linters runner.
Usage:
golangci-lint [flags]
golangci-lint [command]
Available Commands:
cache Cache control and information
completion Generate the autocompletion script for the specified shell
config Config file information
custom Build a version of golangci-lint with custom linters
help Help
linters List current linters configuration
run Run the linters
version Version
Flags:
--color string Use color when printing; can be 'always', 'auto', or 'never' (default "auto")
-h, --help Help for a command
-v, --verbose Verbose output
--version Print version
Use "golangci-lint [command] --help" for more information about a command.
vscode 集成配置
"go.lintTool": "golangci-lint",
"go.lintFlags": [
"--fast"
]
常用命令
golangci-lint run
# disable all, enable errcheck
golangci-lint run --disable-all -E errcheck
golangci-lint help linters
配置
.golangci.yml
.golangci.yaml
.golangci.toml
.golangci.json
排除代码检查
var bad_name int //nolint
var bad_name int //nolint:golint,unused
//nolint
func allIssuesInThisFunctionAreExcluded() *string {
// ...
}
//nolint:govet
var (
a int
b int
)
# 整个文件生效
//nolint:unparam
package pkg
示例一
run:
deadline: 12m
timeout: 10m
go: '1.21'
linters:
enable:
- depguard
- godot
- gofumpt
- goimports
- revive
- whitespace
issues:
exclude-rules:
- path: _test.go
linters:
- errcheck
linters-settings:
depguard:
rules:
Main:
deny:
- pkg: sync/atomic
desc: Use go.uber.org/atomic instead of sync/atomic
- pkg: github.com/stretchr/testify/assert
desc: Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert
- pkg: github.com/pkg/errors
desc: Use fmt.Errorf instead
errcheck:
exclude-functions:
- (hash.Hash).Write
goimports:
local-prefixes: github.com/xiexianbin/go-echo-demo
gofumpt:
extra-rules: true
misspell:
locale: US
revive:
rules:
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return
- name: unexported-return
severity: warning
disabled: true
示例二
# https://golangci-lint.run/usage/quick-start/
run:
timeout: 12m
skip-dirs:
- dist
- docs
- examples
- hack
- manifests
- pkg/client
- sdks
- ui
- vendor
skip-files:
- server/static/files.go
build-tags:
- api
- cli
- cron
- executor
- examples
- corefunctional
- functional
- plugins
linters:
enable:
- asasalint
- bidichk
- bodyclose
- errcheck
- exportloopref
- goimports
# only minor issues
# - errorlint
# seems to have bugs in recent version, also slow
# - gci
- gosec
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- nosprintfhostport
- reassign
- rowserrcheck
- sqlclosecheck
- staticcheck
- typecheck
- unparam
- unused
linters-settings:
goimports:
local-prefixes: github.com/argoproj/argo-workflows/
gosec:
includes:
- G304
- G307
excludes:
# G106: Use of ssh InsecureIgnoreHostKey should be audited
- G106
# G402: TLS InsecureSkipVerify set true
- G402
# G601: Implicit memory aliasing in for loop.
- G601
issues:
exclude-rules:
- path: server/artifacts/artifact_server_test.go
text: "response body must be closed"
示例三
run:
timeout: 5m
skip-dirs:
- pkg/client
- vendor
- "eventsources/common/naivewatcher"
skip-files:
- ".*generated.*"
linters:
enable:
- deadcode
# - depguard
- dogsled
- goconst
- gocritic
- gofmt
- goimports
- goprintffuncname
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- rowserrcheck
- staticcheck
# - structcheck
- typecheck
- unconvert
- unused
- varcheck
- whitespace
示例四
issues:
exclude:
- SA1019
- SA5011
exclude-rules:
- path: "(applicationset|cmd|cmpserver|controller|pkg|reposerver|server|test)/"
text: "require-error:"
linters:
- testifylint
- path: "util/(argo|cache|cert|clusterauth|config|db|dex|git|gpg|grpc|helm|http|io|kube|kustomize|lua|notification|oidc|rbac|security|session|settings|tls|webhook)/"
text: "require-error:"
linters:
- testifylint
max-issues-per-linter: 0
max-same-issues: 0
linters:
enable:
- errcheck
- errorlint
- gocritic
- gofumpt
- goimports
- gosimple
- govet
- ineffassign
- misspell
- staticcheck
- testifylint
- unused
- whitespace
linters-settings:
gocritic:
disabled-checks:
- appendAssign
- assignOp # Keep it disabled for readability
- badCond
- commentFormatting
- exitAfterDefer
- ifElseChain
- mapKey
- singleCaseSwitch
- typeSwitchVar
goimports:
local-prefixes: github.com/argoproj/argo-cd/v2
testifylint:
enable-all: true
disable:
- error-is-as
- float-compare
- go-require
run:
timeout: 50m
与其他工具集成
Makefile
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
.PHONY: go/deps
go/deps:
go mod tidy
# renovate: datasource=go depName=mvdan.cc/gofumpt
GOFUMPT_VERSION := v0.6.0
gofumpt:
ifeq (, $(shell command -v gofumpt >/dev/null))
go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION)
GOFUMPT=$(GOBIN)/gofumpt
else
GOFUMPT=$(shell command -v gofumpt)
endif
# Rather than running this over and over we recommend running gofumpt on save with your editor.
# Check https://github.com/mvdan/gofumpt#installation for instructions.
.PHONY: go/fmt
go/fmt: gofumpt
$(GOFUMPT) -l -w $(shell go list -f {{.Dir}} ./... | grep -v gen/proto)
.PHONY: go/lint
go/lint:
golangci-lint run
.PHONY: go/test
go/test:
go test $(SANITIZERS) -tags assert -v `go list ./...`
.PHONY: go/bench
go/bench:
mkdir -pm 777 tmp/
go test $(SANITIZERS) -run=. -bench=. -benchtime=1x -v `go list ./...` # run benchmark with one iteration to make sure they work
GOLANGCI_LINT_VERSION := v1.59.1
golangci-lint:
ifeq (, $(shell command -v golangci-lint >/dev/null))
go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}
endif
# or
.PHONY: go/lint
go/lint: golangci-lint
golangci-lint run --fix
# go mod tidy
# golangci-lint run --fix --verbose --concurrency 4 --timeout 5m --enable goimports
github actions
name: golangci-lint
on:
push:
tags:
- v*
branches:
- main
- release-*
pull_request:
branches:
- main
- release-*
merge_group:
branches:
- main
jobs:
lint:
name: Go Lint
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version-file: .go-version
cache: false
...
- name: Install dependencies
run: make go/deps
- name: Build
run: make go/build
- name: Format
run: make go/fmt && git diff --exit-code # ':!ui/packages/app/web/build'
- name: Lint
run: make go/lint
扩展
gofumpt
gofumpt 在 gofmt
的基础上添加了一系列更加严格的格式化规则,并保证对 gofmt
的兼容
go install mvdan.cc/gofumpt@latest
"go.useLanguageServer": true,
"gopls": {
"formatting.gofumpt": true,
}