--- /dev/null
+<!--(
+ "Title": "Staticcheck"
+)-->
+
+
+<h2 id="overview">Overview</h2>
+
+<p>
+ Staticcheck is a static analysis toolset for the <a href="https://golang.org">Go programming language.</a>
+ It comes with a large number of checks,
+ integrates with various Go build systems
+ and offers enough customizability to fit into your workflows.
+</p>
+
+<h2 id="installation">Installation</h2>
+
+<p>
+ There are various ways in which you can install staticcheck,
+ but they all boil down to obtaining the command located at <code>honnef.co/go/tools/cmd/staticcheck</code>
+</p>
+
+<p>
+ If you use Go modules, you can simply run <code>go get honnef.co/go/tools/cmd/staticcheck</code> to obtain the latest released version.
+ If you're still using a GOPATH-based workflow, then the above command will instead fetch the master branch.
+ It is suggested that you explicitly check out the latest release branch instead, which is currently <code>2020.1.5</code>.
+ One way of doing so would be as follows:
+</p>
+
+<pre><code>cd $GOPATH/src/honnef.co/go/tools/cmd/staticcheck
+git checkout 2020.1.4
+go get
+go install
+</code></pre>
+
+<p>
+ Alternatively, you can <a href="https://github.com/dominikh/go-tools/releases">download pre-compiled binaries from GitHub.</a>
+</p>
+
+<p>
+ If you'd like to be notified of new releases, you can use GitHub's
+ <a href="https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository"><em>Releases only</em> watches</a>.
+</p>
+
+<h2 id="running-the-tools">Running staticcheck</h2>
+
+<p>
+ Staticcheck can be run on code in several ways,
+ mimicking the way the official Go tools work.
+ At the core, it expects to be run on well-formed Go packages.
+ The most common way of specifying packages is via their import paths.
+ One or more packages can be specified in a single command,
+ and the <code>...</code> glob operator is supported.
+ All of the following examples are valid invocations:
+
+ <pre><code>staticcheck github.com/example/foo
+staticcheck github.com/example/foo github.com/example/bar
+staticcheck github.com/example/...</code></pre>
+</p>
+
+<p>
+ In addition, a single package can be specified as a list of files:
+
+ <pre><code>staticcheck file1.go file2.go file3.go</code></pre>
+
+ Note that <strong>all</strong> files of the package need to be specified,
+ similar to how <code>go build</code> works.
+</p>
+
+<h2 id="configuration">Configuration</h2>
+
+<p>
+ Various aspects of staticcheck can be customized with configuration files.
+</p>
+
+<p>
+ These files are placed in Go packages and apply recursively to the package tree rooted at the containing package.
+ For example, configuration placed in <code>pkg</code> will apply to <code>pkg</code>, <code>pkg/subpkg</code>, <code>pkg/subpkg/subsubpkg</code> and so on.
+</p>
+
+<p>
+ Configuration files in subpackages can override or inherit from settings of configuration files higher up the package tree.
+ Staticcheck's default configuration is represented as the virtual root of the configuration tree and can be inherited from.
+</p>
+
+<h3>Configuration format</h3>
+
+<p>
+ Staticcheck configuration files are named <code>staticcheck.conf</code> and contain <a href="https://github.com/toml-lang/toml">TOML</a>.
+</p>
+
+<p>
+ Any set option will override the same option from further up the package tree,
+ whereas unset options will inherit their values.
+ Additionally, the special value <code>"inherit"</code> can be used to inherit values.
+ This is especially useful for array values, as it allows adding and removing values to the inherited option.
+</p>
+
+<p>
+ The special value <code>"all"</code> matches all possible values.
+ Currently, this is only used when enabling checks.
+</p>
+
+<p>
+ Values prefixed with a minus sign,
+ such as <code>"-S1000"</code>
+ will exclude values from a list.
+ This can be used in combination with <code>"all"</code> to express "all but",
+ or in combination with <code>"inherit"</code> to remove values from the inherited option.
+</p>
+
+<h3>Options</h3>
+
+<p>
+ A list of all options and their explanations can be found on the <a href="/docs/options">Options</a> page.
+</p>
+
+<h3>Example configuration</h3>
+
+<p>
+ The following example configuration is the textual representation of staticcheck's default configuration.
+</p>
+
+<pre><code>{{ option "checks" }} = ["all", "-{{ check "ST1000" }}", "-{{ check "ST1003" }}", "-{{ check "ST1016" }}"]
+{{ option "initialisms" }} = ["ACL", "API", "ASCII", "CPU", "CSS", "DNS",
+ "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID",
+ "IP", "JSON", "QPS", "RAM", "RPC", "SLA",
+ "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL",
+ "UDP", "UI", "GID", "UID", "UUID", "URI",
+ "URL", "UTF8", "VM", "XML", "XMPP", "XSRF",
+ "XSS"]
+{{ option "dot_import_whitelist" }} = []
+{{ option "http_status_code_whitelist" }} = ["200", "400", "404", "500"]</code></pre>
+
+<h2 id="cli">Command-line flags</h2>
+
+<p>
+ In addition to configuration files, some aspects of staticcheck can be controlled via command-line flags.
+ These are settings that can vary between individual invocations or environments (CI, editors, ...) and shouldn't be stored in configuration files.
+</p>
+
+<table class="table">
+ <tr>
+ <th>Flag</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td>-checks</td>
+ <td>
+ Allows overriding the list of checks to run.
+ Has the same syntax as the <a href="/docs/options#checks"><code>checks</code></a> setting
+ in configuration files.
+ </td>
+ </tr>
+ <tr>
+ <td>-explain</td>
+ <td>
+ Print the description of a check.
+ </td>
+ </tr>
+ <tr>
+ <td>-f</td>
+ <td>
+ Select between the different <a href="/docs/formatters">output formats</a>.
+ </td>
+ </tr>
+ <tr>
+ <td>-fail</td>
+ <td>
+ Specify the list of checks which,
+ if they find any issues in your code,
+ should cause staticcheck to exit with a non-zero status.
+ This can be used, for example, to not fail your CI
+ pipeline because of possible code simplifications.
+ </td>
+ </tr>
+ <tr>
+ <td>-go</td>
+ <td>
+ Select the Go version to target.
+ See
+ <a href="#targeting-go-versions">Targeting Go versions</a>
+ for more details.
+ </td>
+ </tr>
+ <tr>
+ <td style="white-space: nowrap">-show-ignored</td>
+ <td>
+ Show all problems found,
+ even those that were ignored by linter directives.
+ </td>
+ </tr>
+ <tr>
+ <td>-tags</td>
+ <td>
+ Similar to <code>go build -tags</code>,
+ allows specifying the build tags to use.
+ </td>
+ </tr>
+ <tr>
+ <td>-tests</td>
+ <td>
+ Include tests in the analysis.
+ </td>
+ </tr>
+ <tr>
+ <td>-unused.whole-program</td>
+ <td>
+ Run unused in whole program mode.
+ </td>
+ </tr>
+ <tr>
+ <td>-version</td>
+ <td>
+ Display the version of staticcheck and exit.
+ </td>
+ </tr>
+</table>
+
+<h2 id="targeting-go-versions">Targeting Go versions</h2>
+
+<p>
+ By default, staticcheck will make suggestions that are correct for the current version of Go.
+ If you're wishing to support older versions of Go,
+ not all suggestions are applicable –
+ some simplifications are only valid for newer versions of Go
+ and deprecated functions may not have had viable alternatives in older versions.
+</p>
+
+<p>
+ To target a specific Go version you can use the <code>-go</code> command line flag.
+ For example, with <code>-go 1.6</code>, only suggestions that are valid for Go 1.6 will be made.
+</p>
+
+<h2 id="ignoring-problems">Ignoring problems</h2>
+
+<p>
+ In general, you shouldn't have to ignore problems reported by staticcheck.
+ Great care is taken to minimize the number of false positives and subjective suggestions.
+ Dubious code should be rewritten and genuine false positives should be reported so that they can be fixed.
+</p>
+
+<p>
+ The reality of things, however, is that not all corner cases can be taken into consideration.
+ Sometimes code just has to look weird enough to confuse tools,
+ and sometimes suggestions, though well-meant, just aren't applicable.
+ For those rare cases, there are several ways of ignoring unwanted problems.
+</p>
+
+<h3 id="line-based-linter-directives">Line-based linter directives</h3>
+
+<p>
+ The most fine-grained way of ignoring reported problems is to annotate the offending lines of code with linter directives.
+</p>
+
+<p>
+ The <code>//lint:ignore Check1[,Check2,...,CheckN] reason</code> directive
+ ignores one or more checks on the following line of code.
+ The <code>reason</code> is a required field
+ that must describe why the checks should be ignored for that line of code.
+ This field acts as documentation for other people (including future you) reading the code.
+</p>
+
+<p>
+ Let's consider the following example,
+ which intentionally checks that the results of two identical function calls are not equal:
+
+ <pre><code>func TestNewEqual(t *testing.T) {
+ if errors.New("abc") == errors.New("abc") {
+ t.Errorf(`New("abc") == New("abc")`)
+ }
+}</code></pre>
+</p>
+
+<p>
+ {{ check "SA4000" }} of staticcheck
+ will flag this code,
+ pointing out that the left and right side of <code>==</code> are identical –
+ usually indicative of a typo and a bug.
+</p>
+
+<p>
+ To silence this problem, we can use a linter directive:
+
+ <pre><code>func TestNewEqual(t *testing.T) {
+ //lint:ignore SA4000 we want to make sure that no two results of errors.New are ever the same
+ if errors.New("abc") == errors.New("abc") {
+ t.Errorf(`New("abc") == New("abc")`)
+ }
+}</code></pre>
+</p>
+
+<h4>Maintenance of linter directives</h4>
+
+<p>
+ It is crucial to update or remove outdated linter directives when code has been changed.
+ Staticcheck helps you with this by making unnecessary directives a problem of its own.
+ For example, for this (admittedly contrived) snippet of code
+
+ <pre><code>//lint:ignore SA1000 we love invalid regular expressions!
+regexp.Compile(".+")</code></pre>
+
+ staticcheck will report the following:
+
+ <pre><code>tmp.go:1:2: this linter directive didn't match anything; should it be removed?</code></pre>
+</p>
+
+<p>
+ Checks that have been disabled via configuration files
+ will not cause directives to be considered unnecessary.
+</p>
+
+<h3 id="file-based-linter-directives">File-based linter directives</h3>
+
+<p>
+ In some cases, you may want to disable checks for an entire file.
+ For example, code generation may leave behind a lot of unused code,
+ as it simplifies the generation process.
+ Instead of manually annotating every instance of unused code,
+ the code generator can inject a single, file-wide ignore directive to ignore the problem.
+</p>
+
+<p>
+ File-based linter directives look a lot like line-based ones:
+
+ <pre><code>//lint:file-ignore U1000 Ignore all unused code, it's generated</code></pre>
+</p>
+
+<p>
+ The only difference is that these comments aren't associated with any specific line of code.
+ Conventionally, these comments should be placed near the top of the file.
+</p>
+
+<p>
+ Unlike line-based directives, file-based ones will not be flagged for being unnecessary.
+</p>
+
+<h2 id="resource-usage">Resource usage</h2>
+
+<p>
+ Static analysis is a rather resource intensive process,
+ having to apply expensive algorithms to a lot of data.
+ Depending on the complexity of the checked code,
+ this can result in many gigabytes of memory usage and minutes (if not hours) of CPU time.
+</p>
+
+<p>
+ To combat the time complexity of static analysis, staticcheck makes use of caching.
+ It reuses Go's build cache as well as its own facts cache to avoid analysing dependencies whenever possible.
+ In development environments, there is usually nothing to do to benefit from these caches.
+ In CI, however, you have to ensure that the caches persist across successive runs of CI.
+ The build cache and fact cache are stored beneath the <code>os.UserCacheDir()</code> directory, in <code>go-build</code> and <code>staticcheck</code> respectively.
+ On Linux, by default, these directories can be found in <code>~/.cache/go-build</code> and <code>~/.cache/staticcheck</code>.
+</p>
+
+<p>
+ The overall memory consumption of staticcheck is controlled by the degree of parallelism.
+ The more CPU cores a system has available, the more packages will be checked in parallel, increasing the total amount of memory needed.
+ Staticcheck respects the <code>GOMAXPROCS</code> environment variable to control the degree of parallelism.
+</p>
+
+<p>
+ Note that reducing <code>GOMAXPROCS</code> only benefits systems with a lot of cores and code bases with a lot of packages.
+ As <code>GOMAXPROCS</code> approaches 1, peak memory usage will be dominated by the most complex package in the code base.
+ Additionally, smaller code bases may have such interconnected dependencies that peak parallelism is never reached, or there may simply be fewer packages than cores.
+ For example, when checking 10 packages it makes no difference if GOMAXPROCS is set to 32 or 16, at most 10 packages can be processed in parallel.
+</p>
+
+<p>
+ Furthermore, a certain amount of type information per package needs to be retained until the end of the process,
+ which means that overall memory usage grows with the number of checked packages.
+ You can reduce this effect by disabling the U1000 and U1001 checks via the <code>-checks</code> command line flag (e.g. via <code>staticcheck -checks="inherit,-U1000,-U1001"</code>).
+</p>
+
+<p>
+ Finally, you can trade execution time for memory usage by setting the <code>GOGC</code> environment variable to a value less than 100.
+ This will run more frequent garbage collection, potentially lowering peak memory usage, at the cost of spending more CPU.
+</p>
+
+
+<h2>Checks</h2>
+
+A list of all checks can be found on the <a href="/docs/checks">Checks</a> page.