Using linters improves readability by highlighting problems before they are executed, and it helps with the standardization of your codebase. A good linter has configuration settings that help to lessen warnings for rules you don’t care about, making code easier to comprehend, modify, and maintain.
In this article, we’ll be learning more about linting through these topics:
golint has been the most widely used linter for Go over the years. Unfortunately, it is now officially deprecated and archived. The issue with golint is that it doesn’t offer any configuration options and always applies all the rules, which leads to warnings for rules you don’t care about. In this article, we’ll use the revive package as well as exploring alternative go linting packages.
Conversely, revive is a fast, configurable, extensible, adaptable, and beautiful linter for Go. It serves as golint’s drop-in replacement.
Here’s how revive is different from golint:
Open a terminal and create a project folder. Navigate to the project folder and run the following command to start a new project:
go mod init project
Navigate to your Go project and run the following command to install the revive linter package:
go install github.com/mgechev/revive@latest
Create a main.go
file and add the following code snippet to the main.go
file:
package main import ( "fmt" ) func main() { PrintName("Emmanuel") PrintAge(23) } func PrintName(name string) { fmt.Println(name) } func PrintAge(age int) { fmt.Println(age) }
Now, run the revive
command on the project terminal and you should get the following report:
main.go:11:1: exported function PrintName should have comment or be unexported main.go:15:1: exported function PrintAge should have comment or be unexported
In Go, the first letter of an exported function is usually an uppercase. A properly documented codebase requires that exported functions be commented with a brief overview of the function’s purpose, so everyone can understand what it does. Now we can see how the revive package helps us write well-documented code.
Now, let’s add some comments to these functions:
... // This function uses the fmt.Println function to print a string. func PrintName(name string) { fmt.Println(name) } // This function uses the fmt.Println function to print a number. func PrintAge(age int) { fmt.Println(age) }
Execute the revive command and you should have the following report:
main.go:12:1: comment on exported function PrintName should be of the form "PrintName ..." main.go:17:1: comment on exported function PrintAge should be of the form "PrintAge ..."
Revive tells us that our comment should begin with the name of our exported functions for a properly documented codebase.
Let’s change our comments to the following:
... // PrintName uses the fmt.Println function to print a string. func PrintName(name string) { fmt.Println(name) } // PrintAge uses the fmt.Println function to print a number. func PrintAge(age int) { fmt.Println(age) }
With this, execute the revive command and you should have no report.
Sometimes, it’s necessary to disable specific linting issues that appear in a file or package. Both comments and exclusion rules in the configuration file can be used to do this. Let’s examine each strategy in turn.
The comments strategy comes in handy when you want to disable warnings for a certain section of code but still want to apply the rule to other parts of the project.
Here is how to disable specific linting issues using comments:
package main import ( "fmt" ) func main() { PrintName("Emmanuel") } // revive:disable:exported func PrintName(name string) { fmt.Println(name) }
The syntax for this is revive
, followed by a colon, then disable
. If desired, add another colon followed by the name of a linter rule.
This is one amazing feature of the revive linter package that address the major challenge with the popular golint
linter package.
Let’s see how to configure the revive linter package to disable some linting rules in order to reduce unnecessary warnings.
Add a file named revive.toml
to the project folder with the default revive
configuration:
ignoreGeneratedHeader = false severity = "warning" confidence = 0.8 errorCode = 0 warningCode = 0 [rule.blank-imports] [rule.context-as-argument] [rule.context-keys-type] [rule.dot-imports] [rule.error-return] [rule.error-strings] [rule.error-naming] [rule.exported] [rule.if-return] [rule.increment-decrement] [rule.var-naming] [rule.var-declaration] [rule.package-comments] [rule.range] [rule.receiver-naming] [rule.time-naming] [rule.unexported-return] [rule.indent-error-flow] [rule.errorf] [rule.empty-block] [rule.superfluous-else] [rule.unused-parameter] [rule.unreachable-code] [rule.redefines-builtin-id]
Now, remove all comments and run the following command to use the linter with the configuration file:
revive -config revive.toml
To disable any of these rules, you can either remove them or add #
before the specified rule as follows:
#[rule.exported]
Some code editors support linting code automatically; Visual Studio Code is one of them.
Let’s see how to set up the revive linter in Visual Studio Code.
Open VS Code and install the go
extension for VS Code. Then, select the File tab > Preferences > Settings and add go.lint
to the search field and select revive in the Go: Lint Tool section.
The default Go linter for Visual Studio Code is staticcheck
.
go vet
commandIn contrast to linters, the go vet command identifies code that compiles but probably won’t perform as intended.
Let’s consider a common self assignment bug in our Golang code. Update main.go
file as follows:
package main import ( "fmt" ) func main() { PrintName("Emmanuel") } // revive:disable:exported func PrintName(name string) { name = name fmt.Println(name) }
The above code will compile even with this bug. Executing the revive linter command won’t report any issue concerning this bug. This is where the go vet
command comes in handy.
Run the go vet
command and you should have the following result instead:
$ go vet # sample .\main.go:10:2: self-assignment of name to name
If revive isn’t your preference, here is a list of Go linters that have been built and maintained by the community.
golangci-lint
is a fast Go linters runner. It integrates with every major IDE, employs caching, enables YAML configuration, executes linters in parallel, and comes with a large number of linters.
staticcheck
is a cutting-edge Go programming language linter. It employs static analysis to identify bugs and performance problems, provide simplifications, and enforce style guidelines.
Go takes documentation seriously because the easier it is for developers to produce good documentation, the better for everyone.
In this article, we’ve explored linting in Golang, my preferred linting package, and alternative packages for linting in Go. I hope you’ll like working with revive!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.