DEV Community

Cover image for ⭐️ Helpful Golang tools to make your code great again
Vic Shóstak
Vic Shóstak

Posted on • Updated on

⭐️ Helpful Golang tools to make your code great again

Introduction

Hello, breathtaking DEV people! 👋

All last week I was refactoring my Go projects. And realized that I was using the same tools to check code quality and safety everywhere. Yes, this should be done from time to time to keep the code base clean and orderly (this applies not only to programming, but in general in life).

🚀 By the way, this article is not about the built-in linters and formatters in the Go plugin for VS Code or similar! These will be different projects from various authors, that you can add to your programming cycle.

So, why not tell my readers about helpful tools? Let's go! 👇

📝 Table of contents

Why it is important and my vision for Go projects

I have to tell you: I love writing code. But more than that, I like reading structured code from other developers.

Why? It helps to better understand the author, adopt useful techniques and methods, as well as, just to understand the work of a particular function and the package as a whole!

For this reason, I am meticulous about tools to make it easier to write code and, as a consequence, to read it afterwards. I encourage you to be careful and use the tips and tools I describe in this article, too… someone is still reading the code you've written.

↑ Table of contents

Setting up the environment correctly

First, the default .editorconfig for all of my Go projects, looks like this:

# ./.editorconfig

root = true

[*] # <-- rules for all files
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[{go.mod,go.sum,*.go}] # <-- rules only for Go's project files
indent_style = tab
indent_size = 4

# ...other rules...
Enter fullscreen mode Exit fullscreen mode

The second, but just as important as the first, always updated Go plugin for Visual Studio Code (which I mentioned above) with default settings.

vs code go

↑ Table of contents

The gosec package

The gosec inspects source code for security problems by scanning the Go AST. This package contains over 30 different rules to test the security of your Go code.

☝️ Note: In computer science, an abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract syntactic structure of source code written in a programming language.

GitHub logo securego / gosec

Golang security checker

Here's an example from one of my projects. I call the command gosec ./... in the root directory of my module:

[gosec] 2021/10/25 18:03:37 Including rules: default
[gosec] 2021/10/25 18:03:37 Excluding rules: default
[gosec] 2021/10/25 18:03:37 Import directory: /Users/koddr/Code/project/api/app/models
[gosec] 2021/10/25 18:03:37 Checking package: models

# ...list of all *.go files...

Results:

[/Users/koddr/Code/project/api/platform/cdn/digitalocean_spaces.go:62] - G304 (CWE-22): Potential file inclusion via variable (Confidence: HIGH, Severity: MEDIUM)
    61:         // Open the file from system path.
  > 62:         file, errOpen := os.OpenFile(pathToFile, os.O_RDONLY, 0o600)
    63:         if errOpen != nil {

Summary:
  Gosec  : 2.9.1
  Files  : 29
  Lines  : 2760
  Nosec  : 0
  Issues : 1
Enter fullscreen mode Exit fullscreen mode

And this give me a lot of information to fix it! You can easily fix this part of the code by wrapping the pathToFile variable with the filepath.Clean() function built into Golang.

🤔 Note: Yes, it may seem strange at first glance, but if you've ever run Go projects in production, you'll understand why you can't leave such things out of your code.

↑ Table of contents

The go-critic package

The go-critic is a collection of checks that detect style, performance issues as well as some common programming errors. It provides as much useful checks as possible. This wonderful tool not only shows you the problematic part of your Go code, but also tells you what to replace it with.

GitHub logo go-critic / go-critic

The most opinionated Go source code linter for code audit.

For an example, let's run gocritic check -enableAll ./... for the popular Swagger documentation generator package swaggo/swag:

./operation.go:1033:24: ioutilDeprecated: ioutil.ReadFile is deprecated, use os.ReadFile instead

./parser.go:604:1: paramTypeCombine: func(tagName string, dirPath string) ([]byte, error) could be replaced with func(tagName, dirPath string) ([]byte, error)

./packages.go:41:5: emptyStringTest: replace `len(packageDir) == 0` with `packageDir == ""`

# ...and over 20 more...
Enter fullscreen mode Exit fullscreen mode

If there is a rule group you don't need at the moment, just disable it via a disable flag with tag like this:

gocritic check -disable='#style' ./...
Enter fullscreen mode Exit fullscreen mode

Supported tags (always enabled):

  • #diagnostic — kind of checks that detect various errors
  • #style — kind of checks that find style issues
  • #performance — kind of checks that detect potential performance issues
  • #security — kind of checks that find security issues

And tags which disabled by default (enable it by the -enable='<TAG>' flag with specific tag, or use -enableAll flag):

  • #experimental — check is under testing and development
  • #opinionated — check can be unwanted for some people

For turn off a specific rule, just run this command:

gocritic check -disable=emptyStringTest ./...
Enter fullscreen mode Exit fullscreen mode

☝️ Note: You can find a complete list of all the rules here.

↑ Table of contents

The golangci-lint package

The golangci-lint is a fast Go linters runner. Most installations of this package performed for CI, but you can use it, for example, as a standard linter in your favorite IDE.

GitHub logo golangci / golangci-lint

Fast linters Runner for Go

The main advantages:

  1. Runs linters in parallel, reuses Go build cache and caches analysis results
  2. YAML-based configuration
  3. Many linters included, no need to install them
  4. Minimum number of false positives because of tuned default settings
  5. Nice output with colors, source code lines and marked identifiers

And yes, personally, I often use it with GitHub Actions to check all incoming PRs for projects in the repositories.

📌 Note: If you missed it, here's my series of articles that will give you insight and practice with GitHub Actions.

The config file for Actions looks like this, for example:

# ./.github/workflows/golangci-lint.yml

name: golangci-lint
on:
  push:
    branches:
      - master
  pull_request:

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v2
        with:
          version: latest
          only-new-issues: true
  # ...
Enter fullscreen mode Exit fullscreen mode

A small demo from the developers of golangci-lint that shows the problematic areas of the Beego web framework (by golangci-lint run command):

Image description

↑ Table of contents

Afterwards

I hope that this article has helped you. Write in the comments if you have any other good tools for checking and formatting code. And be never afraid to take a little time to make your code great again.

It's well worth it! 😉

↑ Table of contents

Photos and videos by

  • Tools authors and Vic Shóstak

P.S.

If you want more articles like this on this blog, then post a comment below and subscribe to me. Thanks! 😘

And, of course, you can support me by donating at LiberaPay. Each donation will be used to write new articles and develop non-profit open-source projects for the community.

Support author at LiberaPay

Discussion (4)

Collapse
tekwizely profile image
TekWizely

Greetings,

/self-promotion:

If you plan to use tools like gosec, go-critic and golangci-lint (and you should!), you might also consider automating their usage with something like pre-commit hooks.

My golang hooks package has built-in support for all 3 tools.

I use them in my own projects ands find it very useful to both reject commits when checks fail, and to make it easy to invoke the checks manually as I'm developing.

Collapse
koddr profile image
Vic Shóstak Author

Hi,

Great addition to the article! Thanks for the link and the (brief) explanation. That's what I write articles for, so we can communicate through them and learn new tools.

Collapse
mariusty profile image
mariusty

Thanks for golangci-lint!

Collapse
koddr profile image
Vic Shóstak Author

Glad this tool helped you! 😉

You can integrate it not only in CI, but just use it via golangci-lint run ./... to check locally.