We’re announcing a new linter for Go that also will be a sandbox for prototyping your ideas in the world of static code analysis.

go-critic is based on these observations:

It’s better to have a “good enough” implementation rather than don’t have it at all.

If a check is opinionated it doesn’t mean that it isn’t useful at all, we can mark it as “opinionated” and give it a try.

Writing yet another linter from scratch is always harder than adding a new check to an existing platform that is simple and well supported.

In this article we’re going to describe the architecture of go-critic, some already implemented checks and write a new check from scratch.

Quick start

$ cd $GOPATH

$ go get -u github.com/go-critic/go-critic/...

$ ./bin/gocritic check-package strings

See full output: https://gist.github.com/Quasilyte/22db23699108a0a04ce7544a552c6caa

gocritic program is able to check separate packages by import path (check-package command) and recursively scan the whole tree for a given directory (check-package command). For example, you can run gocritic over whole GOROOT or GOPATH by one of this command:

$ gocritic check-project $GOROOT/src

$ gocritic check-project $GOPATH/src

There are plans to add go-critic to gometalinter & golangci-lint.

How it was started

While doing a regular code review of a Go project or auditing a 3rd party lib you can see the same problems again and again.

Unfortunately, you’ve failed to find a linter that could detect such problems.

Your first step could be problem categorization, then contacting some existing linter maintainers to propose a new check. Chances that your proposal will be approved & merged heavily depends on the project and might be quite low. Also, this might take some time…

But what if your check is controversial and someone might decide that it’s very opinionated?

go-critic was created to become a sandbox and a home for such checks, that is easier to implement rather than asking to merge into existing linter.

go-critic minimizes the amount of work to be done to create a new linter. We can say that it’s enough to add only one file (except tests 😉).

How does go-critic works?

Critic is a collection of rules that describe diagnostic properties and micro-linters (checkers) that perform source code inspection to find rule violations.

Application that embeds linter (ex. cmd/gocritic or golangci-lint) receives a list of supported rules, filters them by their properties, creates a check function and runs each of them on analyzing package.

Adding new checker consists of 3 steps:

Adding tests

Adding implementation of check

Adding documentation for a linter

Let’s go through all of this steps for captLocal linter that suggests renaming parameters those name start with a capital letter.