⭐️ Helpful Golang tools to make your code great again
Tags: go, beginners, programming, productivity
Published: 2021-10-25 16:38:59

## 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](https://marketplace.visualstudio.com/items?itemName=golang.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! 👇

<a name="toc"></a>
### 📝 Table of contents

- [Why it is important and my vision for Go projects](#why-it-is-important-and-my-vision-for-go-projects)
- [Setting up the environment correctly](#setting-up-the-environment-correctly)
- [The gosec package](#the-gosec-package)
- [The go-critic package](#the-gocritic-package)
- [The golangci-lint package](#the-golangcilint-package)
- [Afterwards](#afterwards)

<a name="#why-it-is-important-and-my-vision-for-go-projects"></a>
## 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](#toc)

<a name="#setting-up-the-environment-correctly"></a>
## Setting up the environment correctly

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

```ini
# ./.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...
```

The second, but just as important as the first, always updated [Go plugin](https://marketplace.visualstudio.com/items?itemName=golang.go) for **Visual Studio Code** (_which I mentioned above_) with default settings.

![vs code go](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bd85jb01jdez65tnyawd.gif)

[↑ Table of contents](#toc)

<a name="#the-gosec-package"></a>
## The gosec package

The `gosec` inspects source code for security problems by scanning the Go AST. This package contains [over 30](https://github.com/securego/gosec#available-rules) 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 securego/gosec no-readme %}

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

```bash
[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
```

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()`](https://pkg.go.dev/path/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](#toc)

<a name="#the-gocritic-package"></a>
## 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 go-critic/go-critic no-readme %} 

For an example, let's run `gocritic check -enableAll ./...` for the popular Swagger documentation generator package [`swaggo/swag`](https://github.com/swaggo/swag):

```bash
./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...
```

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

```bash
gocritic check -disable='#style' ./...
```

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:

```bash
gocritic check -disable=emptyStringTest ./...
```

> ☝️ **Note:** You can find a complete list of all the rules [here](https://go-critic.com/overview.html#checkers).

[↑ Table of contents](#toc)

<a name="#the-golangcilint-package"></a>
## 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 golangci/golangci-lint no-readme %}

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](https://dev.to/koddr/series/7074) that will give you insight and practice with GitHub Actions.

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

```yml
# ./.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
  # ...
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mps4v43pepd9h1rvm6pc.png)](https://asciinema.org/a/183662)

[↑ Table of contents](#toc)

<a name="#afterwards"></a>
## 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](#toc)

<a name=""></a>
## Photos and videos by

- Tools authors and Vic Shóstak

<a name=""></a>
## 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 help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv