goimports vs gofmt

It is hard to find a Go developer who have never heard of gofmt. From the moment we start learning the language, Go documentation including Effective Go preaches us that code MUST be formatted with standard gofmt tool. While gofmt attracks much attention, goimport is overlooked despite often being more useful. In this post we will learn how they differ on example.

Example

Snippet of our unformatted example:

package main

import (
        "encoding/json"
        "fmt"
        "os"  // unused package
        "goji.io"
        "golang.org/x/net/context"
        "net/http"
        "goji.io/pat"
)

type book struct {
        ISBN  string "json:isbn"
        Title  string "json:name"
        Authors string "json:author"
        Price string "json:price"
}

...

gofmt

gofmt goes out of the box and enforces Go code style. It is one of corner stones of Go success. Let’s have a look at how it works. Running go ftm on the example will produce:

package main

import (
        "encoding/json"
        "fmt"
        "goji.io"
        "goji.io/pat"
        "golang.org/x/net/context"
        "net/http"
        "os" // unused package
)

type book struct {
        ISBN    string "json:isbn"
        Title   string "json:name"
        Authors string "json:author"
        Price   string "json:price"
}

...

As you can see, gofmt formatted fields of the struct and sorted import statements in alphabetical order. Note that packages from standard library mixed with third party packages, and unused import is still there.

goimports

goimport does everything that gofmt do. Additionally it groups and corrects imported packages. While correcting, goimports removes unused imports and adds missing ones.

It is so convenient, that most Go programmers prefer goimports to gofmt nowadays. Let’s have a look at how it works. Running goimports on the example will change it to:

package main

import (
        "encoding/json"
        "fmt"
        "net/http"

        "goji.io"
        "goji.io/pat"
        "golang.org/x/net/context"
)

type book struct {
        ISBN    string "json:isbn"
        Title   string "json:name"
        Authors string "json:author"
        Price   string "json:price"
}

...

This output looks much better than output of gofmt. Not only packages are sorted alphabetically, but also they are grouped. Now it is crystal clear which packages are from standard library and which are third parties. Unused package is gone.

We basically could stop here, but let’s have a look at one more trick. Try to remove all import statements and run goimports again. You would be surprised to find that goimports added all missing packages back, sorted and grouped. Be careful with this feature though. If there are multiple packages available with the same name, there is a chance that goimports will choose the wrong one.

Bottom line

Use goimports instead of goftm unless you really need it.