govet: Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false]
errcheck: Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false]
staticcheck: Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false]
unused: Checks Go code for unused constants, variables, functions and types [fast: false]
gosimple: Linter for Go source code that specializes in simplifying a code [fast: false]
gas: Inspects source code for security problems [fast: false]
structcheck: Finds an unused struct fields [fast: false]
varcheck: Finds unused global variables and constants [fast: false]
ineffassign: Detects when assignments to existing variables are not used [fast: true]
deadcode: Finds unused code [fast: false]
typecheck: Like the front-end of a Go compiler, parses and type-checks Go code [fast: false]
We compare golangci-lint and gometalinter in default mode, but explicitly enable all linters because of small differences in the default configuration.
Golangci-lint directly calls linters (no forking) and reuses 80% of work by parsing program only once.
Read [this section](#internals) for details.
# Internals
1. Work sharing
The key difference with gometalinter is that golangci-lint shares work between specific linters (golint, govet, ...).
We don't fork to call specific linter but use its API.
For small and medium projects 50-90% of work between linters can be reused.
* load `loader.Program` once
We load program (parsing all files and type-checking) only once for all linters. For the most of linters
it's the most heavy operation: it takes 5 seconds on 8 kLoC repo and 11 seconds on `$GOROOT/src`.
* build `ssa.Program` once
Some linters (megacheck, interfacer, unparam) work on SSA representation.
Building of this representation takes 1.5 seconds on 8 kLoC repo and 6 seconds on `$GOROOT/src`.
`SSA` representation is used from a [fork of go-tools](https://github.com/dominikh/go-tools), not the official one.
* parse source code and build AST once
Parsing one source file takes 200 us on average. Parsing of all files in `$GOROOT/src` takes 2 seconds.
Currently we parse each file more than once because it's not the bottleneck. But we already save a lot of
extra parsing. We're planning to parse each file only once.
* walk files and directories once
It takes 300-1000 ms for `$GOROOT/src`.
2. Smart linters scheduling
We schedule linters by a special algorithm which takes estimated execution time into account. It allows
to save 10-30% of time when one of heavy linters (megacheck etc) is enabled.
3. Improved program loading
We smartly use setting `TypeCheckFuncBodies` in `loader.Config` to build `loader.Program`.
If there are no linters requiring SSA enabled we can load dependencies of analyzed code much faster
by not analyzing their functions: we analyze only file-level declarations. It makes program loading
10-30% faster in such cases.
4. Don't fork to run shell commands
All linters are vendored in the `/vendor` folder: their version is fixed, they are builtin
and you don't need to install them separately.
# Trusted By
The following great projects use golangci-lint:
* [GoogleContainerTools/skaffold](https://github.com/GoogleContainerTools/skaffold/blob/master/hack/linter.sh#L24) - Easy and Repeatable Kubernetes Development
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser/blob/master/Makefile#L47) - Deliver Go binaries as fast and easily as possible
* [goreleaser/nfpm](https://github.com/goreleaser/nfpm/blob/master/Makefile#L43) - NFPM is Not FPM - a simple deb and rpm packager written in Go
* [goreleaser/godownloader](https://github.com/goreleaser/godownloader/blob/master/Makefile#L37) - Download Go binaries as fast and easily as possible
* [asobti/kube-monkey](https://github.com/asobti/kube-monkey/blob/master/Makefile#L12) - An implementation of Netflix's Chaos Monkey for Kubernetes clusters
- [govet](https://golang.org/cmd/vet/) - Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
- [errcheck](https://github.com/kisielk/errcheck) - Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
- [staticcheck](https://staticcheck.io/) - Staticcheck is a go vet on steroids, applying a ton of static analysis checks
- [unused](https://github.com/dominikh/go-tools/tree/master/cmd/unused) - Checks Go code for unused constants, variables, functions and types
- [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) - Linter for Go source code that specializes in simplifying a code
- [gas](https://github.com/GoASTScanner/gas) - Inspects source code for security problems
- [structcheck](https://github.com/opennota/check) - Finds an unused struct fields
- [varcheck](https://github.com/opennota/check) - Finds unused global variables and constants
- [ineffassign](https://github.com/gordonklaus/ineffassign) - Detects when assignments to existing variables are not used
- [golint](https://github.com/golang/lint) - Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
- [interfacer](https://github.com/mvdan/interfacer) - Linter that suggests narrower interface types
- [unconvert](https://github.com/mdempsky/unconvert) - Remove unnecessary type conversions
- [dupl](https://github.com/mibk/dupl) - Tool for code clone detection
- [goconst](https://github.com/jgautheron/goconst) - Finds repeated strings that could be replaced by a constant
- [gocyclo](https://github.com/alecthomas/gocyclo) - Computes and checks the cyclomatic complexity of functions
- [gofmt](https://golang.org/cmd/gofmt/) - Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
- [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports) - Goimports does everything that gofmt does. Additionally it checks unused imports
- [maligned](https://github.com/mdempsky/maligned) - Tool to detect Go structs that would take less memory if their fields were sorted
- [megacheck](https://github.com/dominikh/go-tools/tree/master/cmd/megacheck) - 3 sub-linters in one: unused, gosimple and staticcheck
- [depguard](https://github.com/OpenPeeDeeP/depguard) - Go linter that checks if package imports are in a list of acceptable packages
-p, --presets strings Enable presets (bugs|unused|format|style|complexity|performance) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all
--fast Run only fast linters from enabled linters set
-e, --exclude strings Exclude issue by regexp
--exclude-use-default Use or not use default excludes:
# errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
# golint: False positive when tests are defined in package 'test'
- func name will be used as test\.Test.* by other packages, and that stutters; consider calling this
# gas: Too many false-positives on 'unsafe' usage
- Use of unsafe calls should be audited
# gas: Too many false-positives for parametrized shell calls
- Subprocess launch(ed with variable|ing should be audited)
# gas: Duplicated errcheck checks
- G104
# gas: Too many issues in popular repos
- (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)
# gas: False positive is triggered by 'src, err := ioutil.ReadFile(filename)'
- Potential file inclusion via variable
# govet: Common false positives
- (possible misuse of unsafe.Pointer|should have signature)
# megacheck: Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore
- ineffective break statement. Did you mean to break out of the outer loop
(default true)
--max-issues-per-linter int Maximum issues count per one linter. Set to 0 to disable (default 50)
--max-same-issues int Maximum count of issues with the same text. Set to 0 to disable (default 3)
-n, --new Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.
It's a super-useful option for integration of golangci-lint into existing large codebase.
It's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code
--new-from-rev REV Show only new issues created after git revision REV
--new-from-patch PATH Show only new issues created in git patch with file path PATH
-h, --help help for run
Global Flags:
-j, --concurrency int Concurrency (default NumCPU) (default 8)
--cpu-profile-path string Path to CPU profile output file
--mem-profile-path string Path to memory profile output file
False positives are inevitable, but we did our best to reduce their count. For example, we have a default enabled set of [exclude patterns](#command-line-options). If a false positive occurred you have the following choices:
1. Exclude issue by text using command-line option `-e` or config option `issues.exclude`. It's helpful when you decided to ignore all issues of this type.
Please create [GitHub Issues here](https://github.com/golangci/golangci-lint/issues/new) if you find any false positives. We will add it to the default exclude list if it's common or we will fix underlying linter.
You can integrate it yourself, see this [wiki page](https://github.com/golangci/golangci-lint/wiki/How-to-add-a-custom-linter) with documentation. Or you can create a [GitHub Issue](https://github.com/golangci/golangci-lint/issues/new) and we will integrate when time permits.
**It's cool to use `golangci-lint` when starting a project, but what about existing projects with large codebase? It will take days to fix all found issues**
We are sure that every project can easily integrate `golangci-lint`, even the large one. The idea is to not fix all existing issues. Fix only newly added issue: issues in new code. To do this setup CI (or better use [GolangCI](https://golangci.com) to run `golangci-lint` with option `--new-from-rev=origin/master`. Also, take a look at option `-n`.
1. Use [GolangCI](https://golangci.com): this service is highly integrated with GitHub (issues are commented in the pull request) and uses a `golangci-lint` tool. For configuration use `.golangci.yml` (or toml/json).
2. Use custom CI: just run `golangci-lint` in CI and check the exit code. If it's non-zero - fail the build. The main disadvantage is that you can't see issues in pull request code and would need to view the build log, then open the referenced source file to see the context.
We don't recommend vendoring `golangci-lint` in your repo: you will get troubles updating `golangci-lint`. Please, use recommended way to install with the shell script: it's very fast.