Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

Go tools provides go/analysis, an API for analysis tools. The documentation clearly explains the aim of this package:

A static analysis is a function that inspects a package of Go code and reports a set of diagnostics (typically mistakes in the code), and perhaps produces other results as well, such as suggested refactorings or other facts

This new interface and tool provided by Go will allow developers to improve their daily work with creating a whole workflow.

Analyzer example

For this article, I will show how to write a custom analyzer that analyses the usage of the contexts in our code. As explained in the documentation, the context should be the first parameter, typically named ctx . The analyzer will make sure the code will respect this recommendation.

The first thing to do when building a custom analyzer is to define the usage of the command:

analyzer name along with documentation

Then, we can define some flags in order to control the usage of our analyzer:

analyzer custom flags

Now that our analyzer is structured, it is time to write the actual logic in the run function. The documentation of the go/analysis package is a great help to understand how to build the code. You can also have a look at the built-in analyzers to get some examples, but it is quite straight forward.

First of all, we have to configure our analyzer to work only on the functions:

Once we’re filtered only on the functions, I will check that each function does not define more than one context, otherwise my two rules defined previously will fail:

Then, it will check the position of the context param and its name:

Our custom analyzer is now ready, let’s test it.

You can find the entire code in my Github repository.

Testing analyzer

Writing your test case is actually the first thing you should do when you build your analyzer. I did show the code first in order to make the lecture more interesting.

Go provides a package, analysistest , that makes the test of our analyzer easy. You just need to create a testdata folder that contains the Go files to be parsed:

folder structure

In each file that is supposed to fail, you can write your assertion message:

message assertion for our custom analyzer

Then you just have to run the helper from analysistest and assert the result:

func TestCtxArg(t *testing.T) {

analysistest.Run(t, analysistest.TestData(), Analyzer)

}

If all assertions are valid, your test will pass.

Standalone command

Go also provides an easy way to create a command from one or multiple analyzers that you can find in my article dedicated to the vet command.

Thanks to the command go install github.com/blanchonvincent/ctxarg , you will generate an executable in your bin directory that you can use in two ways:

directly in command line with passing the package name /path/src/bin/ctxarg ./my-pkg/ .

. in the go vet command thanks to go vet -vettool=$(which ctxarg) ./my-pkg/ .

This executable can also now easily be integrated in your IDE or in your CI environment.