Golang Best Practices (Top 10)

Golang Best Practices

Go, the programming language is one of few languages that have built-in concurrency and has been built with a specific purpose. All programmers who have just started learning Go would, therefore, benefit from this list of best practices, so let’s get started.

This list is divided in sections on the basis of functionality.

Syntax

Go is a static, compiled language. This means that there are some rules that we must adhere to. This will also ensure less confusion while working within a large team, where each group must write their own code and make it compatible with the others.

1. Specify datatypes to new variables that you create

It seems quite easy to just use the walrus operator (:=) for everything. But when your code is in range of a few thousand lines, it can get pretty confusing both for yourself and other teams especially if there is an error to trace back. Also, it just looks so elegant:

func main(){
var x int = 2020
//do something
}

2. Don’t define a variable/import a package that you don’t need

Go automatically removes unused variables and packages in some IDEs, while it throws an error otherwise. This may get confusing to beginners and is often a hassle you’ll face during debugging. The best way to solve this problem is use the comment tags:

//this is a single line comment
/*this is
a
multi-line comment*/

3. Use appropriate naming conventions

A good name is consistent, short and easily comprehensible.

  • Use MixedCase for all names in Go. Don’t use underscores like python.
  • Acronyms should be all capitals.
  • Keep local variables short. Common variables like an index or a loop argument may be a single letter.

4. Use comments for knowledge transfer

When more than one programmer is working on a certain piece of code. It is common practice to leave a brief description in the source code detailing the name of the module, its purpose, and name of the author. Furthermore, it is also appropriate to add an explanation within a complicated piece of code.

Simple, Readable Maintainable Code

1. Handle errors first and avoid nesting

Francesc Campoy, one of the developers on the internal Go team advises in his presentations that it is better to check for a nil error at the beginning of the program. This simplifies the code and reduces load on the reader.

2. Avoiding repetitions with utilities

Go provides certain “utility types” that have been optimised to perform certain functions, for example , binWriter can reduce a 20-line code with repetitions to 12 lines:

if w.err = binary.Write(w.w, binary.LittleEndian, v); w.err == nil {
        w.size += int64(binary.Size(v))
    }

//little Endian is just a font. nothing exotic.

3. Use Type switch to handle special cases

A switch statement is a shorter way to write a sequence of if – else statements. It runs the first case whose value is equal to the condition expression.

Go’s switch resembles the one in C, C++, Java, JavaScript, and PHP, but then again Go only runs the chosen case, not all the cases that follow. In effect, the break statement that is needed at the termination of each case in those languages is provided automatically in Go. Another significant distinction is that Go’s switch cases need not be constants, and the values included need not be integers.

func (struct_name) Write(v input) {
    if err != nil { //error handling first
        return
    }
    switch x := v.(type) {
    case string:
        //do something
    case int:
        //do some other thing
    default:
        //yet another thing
        }
    }
}

4. Organisation of Go code

Let’s look at how an ideal Go program/package code should be organised.

  • Important code goes first ,i.e, License information, build tags, package documentation.
  • Next are the Import statements, related groups separated by blank lines.
  • The rest of the code should be presented starting with the most significant types, and ending with helper functions.

For programmers writing Go packages, it is good practice to separate the code into multiple shorter files – like separate code and tests, because the test codes will only be compiled at runtime. Also, when we have more than one file in a package, it’s convention to create a doc.go file containing the package documentation.

Also, while using go routines, quit channel when your function is done with that channel to avoid leakage.

For CI/CD workflows

In a production development environment, CI/CD stand for Continuous Integration and Continuous Delivery. And with Golang, it is extremely easy to practice CI/CD with the same kind of efficiency. With JFrog’s contribution of a public Go registry, and Artifactory’s native support for Golang, the path to quality CI/CD is much clearer.

1. Use Go Modules

It is a common mechanism for managing versioned dependencies. In your own code, you can import this Go module alongside other dependencies:

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

// Public Go Module for logging
	log "github.com/sirupsen/logrus"
)

Then you can reference the module functions in your Golang code:

   // Send text to the log
   log.Printf("Hello Log!")

2. Use GOPROXY to Ensure Immutability and Availability

Build each Docker image once and promote it through a series of staging repositories. In this way, you can guarantee that what was tested is exactly what is being released to production.

Once you keep your Golang dependencies as formed modules, you can keep them as immutable entities by setting up a GOPROXY. In this way, you can always guarantee what a specific version of a module contains, so your builds are always repeatable.

Conclusion

These are not compulsory but as Wikipedia puts it:

“A best practice is a method or technique that has consistently shown results superior to those achieved with other means”

References