Installing Go

Installation

The Go Downloads page contains binary distributions of Go for Windows, Apple macOS, and Linux.

You can also find instructions for installing Go from source on their Installing Go from source page. We recommend installing a binary release first, as there are extra steps necessary to install from source. You only need to install from source if you’re planning to contribute changes upstream to the Go language.

Also, if you use Homebrew on macOS, you can install with brew install go.

Once installed, test the command by running:

$ go version

and you should see something like:

go version go1.15.6 darwin/amd64

Writing Code

You can write Go code anywhere on your filesystem. Let’s assume that you have a folder in your home directory called ~/code. Let’s also assume that you use GitHub for hosting your source code. Make a new folder in ~/code called myapp, then run:

go mod init github.com/[yourusername]/myapp.

You should have a go.mod file now with your package name in it. Now make a main.go file with the following contents:

1 package main
2 
3 import "fmt"
4 
5 func main() {
6 	fmt.Println("Hello, world")
7 }

and run it:

go run main.go

You should see the “Hello, world” output.

Next, let’s add a dependency with go get.

When you retrieve a package using the go get command, the source is downloaded into your $GOPATH/pkg/mod dir (note: if you haven’t set the $GOPATH environment variable explicitly, Go will use $HOME/go as your $GOPATH). A line for that import is also added to your go.mod file. For example, if you want to download the popular URL router library gorilla/mux, you can run:

The go get command downloads the pacakge’s source into your $GOPATH/pkg/mod dir (note: if you haven’t set the $GOPATH environment variable explicitly, Go will use $HOME/go as your $GOPATH). A line for that import is also added to your go.mod file. For example, if you want to download the popular URL router library gorilla/mux, run:

go get github.com/gorilla/mux

and Go will download the source into (assuming the latest version is 1.8.0) $GOPATH/pkg/github.com/gorilla/mux@v1.8.0. You can now import that library in your code:

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "net/http"
 6 
 7     "github.com/gorilla/mux"
 8 )
 9 
10 func HomeHandler(w http.ResponseWriter, r *http.Request) {
11     fmt.Fprintf(w, "Hello, world")
12 }
13 
14 func main() {
15     r := mux.NewRouter()
16     r.HandleFunc("/", HomeHandler)
17     http.Handle("/", r)
18     http.ListenAndServe(":8080", r)
19 }

and you can run go run main.go again and curl localhost:8080 should respond with Hello, world.

Your go.mod should now look like this:

1 module github.com/[yourusername]/myapp
2 
3 go 1.15
4 
5 require github.com/gorilla/mux v1.8.0

If you prefer to vendor your dependencies, you can run go mod vendor and Go will create a vendor/ directory for you with the appropriate dependencies. When the Go toolchain recognizes that you have a vendor/ directory it will choose to use that during compilation.

Editor Integrations

Since there are so many editors and IDEs out there, we will only briefly cover three common editors: Goland by JetBrains, vim and Sublime Text. We will link to relevant information for other popular editors at the end of the section.

For all editors, we recommend running goimports on save. Like the gofmt command, goimports formats your Go code, but it also adds or removes imports. If you reference mux.NewRouter in your code but have not yet imported github.com/gorilla/mux, goimports will find the package and import it. It also works for the standard library, which is especially useful for functions like fmt.Println. It is worthwhile to ensure your editor has the goimports plugin: it will speed up your Go development process.

Goimports can be installed with go get:

1 go get golang.org/x/tools/cmd/goimports

We now discuss some useful plugins for three common editors, in (arguably!) decreasing order of complexity.

GoLand

GoLand is a powerful and mature IDE for Go. It features code completion, the ability to jump to variable and type definitions, standard debugging tools like run-time inspection and setting break points, and more. A free 30-day trial can be downloaded from https://www.jetbrains.com/go/

Once installed, we recommend installing goimports on save. To do this, go to File -> Settings -> Tools -> File Watchers. Click the Plus (+) icon, and select “goimports”. Press OK. When you now save a Go file in the project, it should get formatted according to Go standards automatically.

Sublime Text

For Sublime Text 3, we recommend installing a package called GoSublime. Sublime Text package control can install this package. Install package control with the commands provided at https://packagecontrol.io/installation. To open package control, press Ctrl+Shift+P on Windows and Linux, or Cmd+Shift+P on OS X. Then type “install package” and select “Package control: install package”. Now type “GoSublime” and choose the matching option. Finally, open the GoSublime settings by going to Preferences -> Package Settings -> GoSublime -> Settings-User. Make sure that GOPATH matches the path you configured earlier. Here are some typical settings:

1 {
2     // you may set specific environment variables here
3     // e.g "env": { "PATH": "$HOME/go/bin:$PATH" }
4     // in values, $PATH and ${PATH} are replaced with
5     // the corresponding environment(PATH) variable, if it exists.
6     "env": {"GOPATH": "$HOME/Code/go", "PATH": "$GOPATH/bin:$PATH" },
7 
8     "fmt_cmd": ["goimports"]
9 }

vim

For vim, you will want to install vim-go. Instructions can be found on that page for the various vim package managers.

Once you have installed vim-go, you can add the following line to your .vimrc file in order to run goimports on save:

let g:go_fmt_command="goimports"

(Optional) Linters and Correctness Tooling

Linters and other types of tooling can help you catch common mistakes in Go code more quickly. By tightening the feedback loop between writing code and finding a bug, having such tools part of your regular workflow will also accelerate your journey to becoming an experienced Go programmer.

To install a suite of linters and tools to run on your code in one simple step, we recommend golangci-lint. For installation instructions in your local environment, see https://golangci-lint.run/usage/install/#local-installation.

golangci-lint allows you to run a variety of linters and tooling and conveniently combines all of their output into a standard format. We’ve found the deadcode, ineffassign, staticcheck and misspell (disabled by default, enable with --enable=misspell) linters to be particularly useful.

To run the default set of linters, run:

$ golanci-lint run

You may also want to disable all but a specific linter, as in the following example where we run only errcheck:

1 golangci-lint run --disable-all -E errcheck

While you may not want to require all the linters to pass in your build, one tool we recommend requiring is go vet. Using golangci-lint, it can be run like this:

1 golangci-lint run --disable-all -E govet

Go vet is a tool concerned with code correctness. It will find problems in your code such as using the wrong string formatting verb in a call to Printf:

1 package main
2 
3 import (
4     "fmt"
5 )
6 
7 func main() {
8     fmt.Printf("%d", "test")
9 }

This code compiles and runs, but if you do actually run it you’ll see this:

$ go run main.go
%!d(string=test)%

because %d is meant for printing integers, not strings. If you were to run go vet on the above code (or equivalently through golangci-lint run), you would see this warning:

$ go vet main.go
main.go:8: arg "test" for printf verb %d of wrong type: string
exit status 1

Another common issue vet will catch for you is the use of printf verbs inside a call to Println:

1 package main
2 
3 import (
4 	"fmt"
5 )
6 
7 func main() {
8 	fmt.Println("%d", "test")
9 }

Again this will compile and run fine, but the output would be this:

$ go run main.go
%d test

Calling go vet on this code will tell you:

$ go vet main.go
main.go:8: possible formatting directive in Println call
exit status 1