Top 11 Golang Best Practices For 2020

Top 11 Golang Best Practices for 2020

Golang’s adoption is increasing day by day. Recently, Golang has been the true norm to build command line tools. For security cases, Go happens to be doing good in their reports for vulnerabilities, with just one CVE registry since 2002. But, not having vulnerabilities doesn’t imply that the programming language is secure. If we don’t follow best practices, the developed app can cause security issues and sometimes it may fail. So, Here we’ll see some best practices that you must consider while developing software with Golang.

Know the amazing new features of Golang 1.15 at- What’s New In Golang 1.15?

Top 11 Golang Best Practices-

1. Use Of HTML Templates-

Cross-site scripting or XSS is one of the most basic and common vulnerabilities. Generally, this consists of the attacker being able to include malicious code in the app to modify the output. For example, one can send a Javascript code as part of the query string in a url. When the app returns user’s value, Javascript code could be executed. So, as a developer, you must know this and sanitize the user’s input. For encoding what the app will return to the use, Golang has a package template/html. Thus, rather than the browser executing an input like <script>alert(‘You’ve Been Hacked!’);</script>, popping up an alert message; you could encode the info, and the application will treat the input as a typical HTML code printed in the browser. HTML server that returns HTML template looks as below-

package main
import (
	"html/template"
	"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
	param1 := r.URL.Query().Get("param1")
	tmpl := template.New("hello")
	tmpl, _ = tmpl.Parse(`{{define "T"}}{{.}}{{end}}`)
	tmpl.ExecuteTemplate(w, "T", param1)
}
func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

You can use third-party libraries while developing web apps with Go. Gorilla web toolkit includes libraries to help developers for encoding authentication cookie values. nosurf, which is an HTTP package that helps with the prevention of cross-site request forgery (CSRF).

2. Validate Input-

Validation of entries from the user is for functionality purpose and it also helps to avoid hackers who send harmful data that could damage the system. Also, you can assist users to use the tool by preventing them from making common and silly mistakes. For example, you can prevent a user from deleting several records at the same time. For the validation of user input, you can use native Go packages like strconv to handle string conversions to other data types. Go has support for regular expression with regexp for complicated validations. Despite the fact that Go’s preference is to use local libraries, there are third-party packages like validator. By using a validator, you can include validations for structs or individual fields more easily. For example, the below code validates that the User struct contains a valid email address:

package main
import (
	"fmt"
 
	"gopkg.in/go-playground/validator.v9"
)
type User struct {
	Email string `json:"email" validate:"required,email"`
	Name  string `json:"name" validate:"required"`
}
func main() {
	v := validator.New()
	a := User{
		Email: "a",
	}
	err := v.Struct(a)
	for _, e := range err.(validator.ValidationErrors) {
		fmt.Println(e)
	}
}

3. Use gofmt-

To automatically fix most of the mechanical style issues, Run gofmt on your code. Gofmt will read the go code and will show the properly aligned output after indentation, vertical alignment and even it can re-format the comments also.

Commands and options-

gofmt filename- It prints the re-formatted code

gofmt -w filename- It will reformat the code and updates the file.

gofmt -r ‘rule’ filename- Apply rewrite rule to source before reformatting.

gofmt /path/to/ package- It will format the whole package

For example-

package main
          import "fmt"
// this is demo to format code
            // with gofmt command
var a int=10;
             var b int=15;
                            var c string= “Welcome to Agira”;
       func print(){
                   fmt.Println("Value for a,b and c is : ");
                        fmt.Println(a);
                                 fmt.Println((b));
                                         fmt.Println(c);
                         }

Passing a Command: $ gofmt demo.go-

package main
import "fmt"
// this is demo to format code
// with gofmt command
var a int = 10
var b int = 15
var c string =  “Welcome to Agira”
func print() {
        fmt.Println("Value for a,b and c is : ")
        fmt.Println(a)
        fmt.Println((b))
        fmt.Println(c)
}

4. Avoid Nesting By Handling Errors First-

Rather than using multiple or nested conditions, we can break the condition if we should confront error while processing and continue further with coding. 

Rather you can do like this:

err := request()
if err != nil {
  // handling error
  return // or continue, etc.
}

Less nesting means less cognitive load on the reader. If the if statement has an initialization statement like:

If x, err :=
f(); err !=nil
{
       //handling
error
return
} else {
   // use x
}

At such a time, this may need to define the short variable declaration in the code:

x, err := f()
if err != nil {
             // handling
error 
       return
}
// use x

5. Protect Yourself From SQL Injections-

While using Go, you must consider some specific things. First one is- ensure that the user that connects to the database has limited permissions. Best practice is to sanitize the user’s input or to escape special characters and use HTMLEscapeString function from the HTML template package.

However, one of the critical part of code you’d need to add is the use of parameterized queries. With Go, you don’t prepare a statement in a connection; you prepare it on DB. Let us see the example, how to use parameterized queries:

customerName := r.URL.Query().Get("name")
db.Exec("UPDATE creditcards SET name=? WHERE customerId=?", customerName, 233, 90)

What will happen if the database engine doesn’t support the use of prepared statements? Or what if it affects the performance of queries? One can make use of the db.Query() function, but ensure that you sanitize the user’s input first. To prevent sqlmap there are third-party libraries such as sqlmap. Some of the times, vulnerabilities slip through, or enter our applications by means of third parties.

Make sure that you protect web applications from critical attacks like SQL injections.

6. Error Strings-

No capitalization of error strings(unless start with proper nouns or acronyms).  For Example:

Rather than thics command fmt.Errorf(“Something went wrong”) you can move with this fmt.Errorf(“something went wrong”)

7. Errors Handling-

Don’t discard errors using _ variables. If function returns an error, just ensure that function succeeded or not. It will be better to handle the error and return it or, that will cause an error when any exceptional situation occurs.

Don’t use panic errors-

For the normal error handling, don’t use panic. In such cases, you can use error and multiple return values.

8. Avoid Repetition When Possible-

If you want to use structures in controllers and models, just create one common file and you can create the structure.

9. Type Switch To Handle Special Cases-

You can use a type switch, if you’re unsure about what the interface{} type.

For instance:

func Write(v interface{}) {
   switch v.(type) {
   case string:
     s := v.(string)
     fmt.Printf("%T\n",s)
   case int:
     i := v.(int)
     fmt.Printf("%T\n",i)
   }
  }

10. Import Dot-

import . form can be used to test the circular dependencies. It cannot be made part of the package being tested:

package foo_test
  import (
  "bar/testutil" // also imports "foo"
  . "foo"
  )

Here, the test file can’t be in package foo as it uses bar/testutil, that imports foo. Thus we use the `import.` form to allow the file pretend to be part of the package for despite the fact that it isn’t. Exceptional to this case, don’t use `import .` in your code. It makes the code a lot harder to read because it is not clear when a name like Quux is a high level identifier in the current package or in an imported package.

11. Important Code Goes First-

A case in which you have the important data like License information, build tags and package documentation at that point describe it prior. You can separate the Import statements, related groups by blank lines. Standard library packages are in the first group.

import (
     "fmt"
     "io"
     "log"
    
   "golang.org/x/net/websocket"
  )

Remaining code starting with important types and ending with helper function and types.

Know the best Golang ide’s at- Best Integrated Development Environment For GOLANG(A 2020 Review).

Wrap up-

These are some of the Go best practices that you must know while starting development. It will surely improve the quality of your code. If you’re thinking to develop a software with golang, consult with solace experts. We are here to help you with our skilled developers. You can hire golang developers of solace team for effective development. Connect with solace and get a free quote for go development. We will be happy to help you.

Related Post