What is A Golang Linter And How To Use It?
Using a Golang linter is a good practice when you start to developing your application.
We, as developers, try to write code that is simple and efficient. However, let’s be honest, we are human and during writing or reviewing our beloved codes, we sometimes forget to remove some unnecessary conditions, employ early return pattern, even notice when we have a shadowed variable.
A Golang linter (pretty much every linter in any programming language) goes beyond checking code styles. Actually it will help us to write better code, fewer conditions, optimizing system memory usage and reducing overall code complexity.
A Golang linter can assist us to us in defining a sound coding rules for nearly every step of coding of coding like: error handling, struct field alignment, prevent exhaustive code, log and dependency rules.
In this story, we will use a Golang Linter called golangci-lint
which can integrate almost all community driven linters. It allows us to configure every step easily and integrates with editors such as VSCode, Goland, Vim and Atom.
All the configurations for this story can be accessed here.
Before anything we need to install golangci-lint
and it’s one straightforward step: (choose one of the following commands)
# first way: binary will be $(go env GOPATH)/bin/golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2
# alternative way: install it into ./bin/
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.55.2
# docker way:
docker run --rm -v $(pwd):/app -v ~/.cache/golangci-lint/v1.55.2:/root/.cache -w /app golangci/golangci-lint:v1.55.2 golangci-lint run -v
To ensure we installed Golang linter properly run this command:
golangci-lint --version
We should see something like:
After that, the fun part begins. Open your favorite editor, navigate to your Golang project, and create a .golangci.yml
file in the root directory to store all our configurations.
Every configuration file can have some major parts. A linters-settings
section includes every linter rules customization. The linters
section which we put linter names to make them enabled to analyze our codes. The run
section is dedicated to tasks we want to execute after running the linter.
We can also add issues
section also to prevent running linter on some specific files like: test files. Until now we have a .golangci.yml
file like below:
We want to make a well-structured and opinionated config file, we start by setting disable-all: true
in the linters
section to enable each golang linter individually. Following that, we add some major and well-known linters to increase code reliability:
Let’s briefly examine some of above the linters mentioned above. For more you can read full documentation and details here.
asasalint
prevent function from having[]any
asany
in variadicfunc(…any)
this will make sure our code behave more predictably and apart from the logger, we generally don’t need these kinds of function parameters in our program, so we will navigate tolinters-settings
section and exclude our log function parameters from being considered as bad code.dupl
linter will detect code duplication with athreshold
of lines that we will determine onlinters-settings
.errcheck
linter will search our codes to find any unhandled error that can harm our application.gosec
check any potential security risk we have in our codes.gomnd
prevent any hard coded number in our code. e.g:3 * time.Second
revive
a very well, extensible and fast golang linter which let us define very strict presets for write better code. (read more here)gocritic
will review our codes for diagnostics, performance and style issues.
Let’s go forward and fill other section with desired settings like below:
By using above file we will prevent: misspelling, hard coded values, potential security issues, duplicate code and constant definition, potential nil pointer dereference, unused parameters, unwanted dependencies, unnecessary type conversion and system memory usage saving when defining struct field.
We will allow 3*time.Second
only when it is used alongside context.WithTimeout(context.Background(), 3*time.Second)
or in the math
package, and …any
in log functions.
We can run golangci-lint run
command to see our code issues and fix them.
Golang Linter Editor Integration
You may integrate golangci-lint
with your editor for instant feedback about your codes.
VSCode integration is so easy just put these in the json settings file:
"go.lintTool": "golangci-lint",
"go.lintFlags": [
"--fast"
]
# using it in an editor without --fast can freeze your editor.
# golangci-lint automatically discovers .golangci.yml config
# you don't need to configure it in VS Code settings.
If you are using Vim, Goland and other editor read here.
ALSO READ: