This document suggests guidelines for usage of the components provided by this repository. Components:
(1) gometalinter
: This tool provides wrappers around a variety of static
analysis tools for golang.
gometalinter
is a tool which wraps about 10-15 other static analysis tools for
golang. They perform a wide range of functions, from checking spelling,
eliminating dead code to optimizing memory layout. The guiding principle when
using these tools is to improve readability & maintainability of the code. Only
use the bits that you find helpful in keeping code quality up, don't be dogmatic
about chasing a 100% correctness.
- Installation/Integration with Makefiles:
common.mk
provides a target to install thegometalinter
. Usage:
# From the command line
$ make -f common.mk install-metalinter
# To use within your own makefile, include `common.mk`,
# and re-use the target as you would normally.
-
Using
gometalinter
: This repository providesmetalint.sh
to wrap the underlying functionality. The easiest way to understand how to use it is to study howm3collector
does it -- Relevant bits from the
Makefile
metalint_check := .ci/metalint.sh metalint_config := .metalinter.json metalint_exclude := .excludemetalint .PHONY: metalint metalint: install-metalinter @($(metalint_check) $(metalint_config) $(metalint_exclude) \ && echo "metalinted successfully!") || (echo "metalinter failed" && exit 1)
- Configuration for the underlying linter,
.metalinter.json
{ "Enable": [ "deadcode", "varcheck", "structcheck", "goconst", "ineffassign", "unconvert", "misspell", "unparam", "megacheck" ], "Deadline": "3m", "EnableGC": true }
- List of exclude dirs,
.excludemetalint
vendor/ generated/ _mock.go
- Relevant bits from the
After this, running make metalint
runs the metalinter and lists applicable
errors (if any). Note: it's suggested to include this target in the Make target
used by .travis.yaml
to ensure the metalinter is run by the CI process too.
Advanced configuration: customising linter arguments
There are instances where you might need to configure the commands run by the sub-linter. For instance, `m3db` needs to specify build tags for it's integration test suite. Here's the `.metalinter.json` configuration it uses for the same:{ "Linters": {
"unused": "unused -tags integration:PATH:LINE:COL:MESSAGE",
"gosimple": "gosimple -tags integration:PATH:LINE:COL:MESSAGE" },
"Enable":
[ "deadcode"
, "varcheck"
, "structcheck"
, "goconst"
, "ineffassign"
, "unconvert"
, "misspell"
, "gosimple"
, "unused" ],
"Deadline": "3m",
"EnableGC": true }
- Which linters to enable?
gometalinter
integrates with 10-15 linters, some which share concerns. I suggest enabling them one at a time, and work through the issues raised by each.
In some cases, you'll find there's too much noise (especially with dupl
, and
gocyclo
). Skim the issues raised and if you don't find anything useful, skip
enabling that particular linter all together.
In other cases, you may find there are certain errors (especially default value for enums) which are raised as false positives. For those cases, you'll have to suppress the warnings using comments. More on this in a section below.
gometalinter
supports suppression of linter messages via comment directives.
The form of the directive is:
// nolint[: <linter>[, <linter>, ...]]
Suppression works in the following way:
-
Line-level suppression
A comment directive suppresses any linter messages on that line.
eg. In this example any messages for
a := 10
will be suppressed and errcheck messages fordefer r.Close()
will also be suppressed.a := 10 // nolint a = 2 defer r.Close() // nolint: errcheck
-
Statement-level suppression
A comment directive at the same indentation level as a statement it immediately precedes will also suppress any linter messages in that entire statement.
eg. In this example all messages for
SomeFunc()
will be suppressed.// nolint func SomeFunc() { }
-
File-level suppression
A comment directive preceding a package directive will also suppress any linter messages in that entire file (note: it only suppresses warnings in that file, not in all files on that package).
eg. In this example all messages for the file will be suppressed.
// nolint package example