Getting started with Go

Installing Go on your system, setting up environment variables, understanding root / workspace directories.

Installation

As we know, a programming language is nothing but a high-level view of the instructions that a CPU can understand and follow (do computation / IO operations demanded in the program).

A language typically consists of the language specifications (syntax), standard library, a runtime environment, and a compiler. When you install Go, these are all the things you will get.

As Go is an open-source and free programming language, you can install it from the source. It also provides compiled binaries to install Go on your system with ease.

It comes with Windows and macOS installer packages which I would recommend if you are using Windows or macOS. All other download and installation related information are available at golang.org.

Go Installation Directory

When you install Go on your system, it creates a directory /usr/local/go in UNIX or c:/go in Windows. Then it copies all necessary code and binaries needed for Go to function in this directory.

This is where Go’s command-line tools, standard library and compiler lives. Whenever you import a package from Go’s standard library, Go looks for the package in this directory.

Custom Installation directory

If somehow, your Go installation directory is different than what Go assumes where it would be, you can use GOROOT environment variable. Edit your ~/.bash_profile and add the below entry. For Windows, follow this answer.

export GOROOT=/usr/local/custom-go

Generally, you don’t need to setup GOROOT environment variable. I recommend not to modify/use GOROOT variable anywhere unless it is absolutely necessary.

Go Workspace

⚠️ … If you are working on Go v1.11+, then you do not need to set up a workspace directory using GOPATH environment variable. You can check the Go version using go version command. Go supports a much better way to manage your project using Go Modules. Follow this article to know more. Go workspaces (GOPATH) will be deprecated soon.

You can create a Go program anywhere you want on your system. A typical Go program is a plain text file with .go file extension. You can run this program using go run hello.go command where hello.go is a Go program file in the current directory.

A workspace is Go’s way to facilitate project management. A workspace, in a nutshell, is a directory on your system where Go looks for source code files, manages dependency packages and build distribution binary files.

Whenever a Go program encounters an import statement, it looks for the package in the Go’s standard library ($GOROOT/src). If the package is not available there, then Go refers to the system’s environment variable GOPATH which is the path to Go workspace directory and looks for packages in $GOPATH/src directory.

You can have as many workspaces as you want, as long as you keep GOPATH environment variable pointed to the current working workspace directory whenever you are working on the given project.

Similar to $GOROOT, $GOPATH by default points to $HOME/go directory in UNIX and %USERPROFILE%\go on windows. Hence, it is not absolutely necessary to setup GOPATH environment variable.

Workspace directory structure

A Go workspace directory must have three sub-directories viz. src, pkg and bin. If you want to set up Go workspace, follow this documentation. If you are using macOS, then you can follow this Medium article to setup environment variables both temporarily or permanently.

src

The src directory contains Go packages. A package in nutshell is a project directory containing Go source code _(_.gofiles)*. Any packages installed usinggo get command will reside here as well (and its dependency packages).

In Go, every program is contained in a package. Hence, whenever you will be working with a new Go project, you need to create a new directory inside $GOPATH/src and work your way up from there.

pkg

The pkg directory contains Go package objects. They are the compiled versions of the original package source code and they have .a file extension (a stands for archived).

These files contain the compiled package binary code, along with debugging symbols and source information. A package object is customized for machine architecture and the Go version. These files are created by the Go pack tool while building/installing a package.

Whenever you install a 3rd party package, a package object package-name.a is created for that package in this directory.

In Go, you typically use import "<package-name>" or import "<main/child-package>" syntax to import a package (like ES6 syntax). Normally, Go looks for these packages in $GOROOT/src or $GOPATH/src directories. But if it finds a precompiled package object associated with an imported package, then Go uses that instead.

Package objects are compiled and archived files for specific platforms. Hence you will see the platform architecture directory inside the pkg directory.

The advantage of having a package object is to save compilation time. As a package is nothing but a collection of Go programs, it has to go through Go compiler every single time the main program (a program who imports it) compiles. If a package has a compiled object file in the pkg directory for current system architecture, then it doesn’t get compiled again.

Therefore when you are referencing foo/bar package. It refers to $GOPATH/pkg/{arch}/foo/bar.a and not $GOPATH/src/foo/bar/*.go (for Go’s standard library package, it will be $GOROOT instead of $GOPATH).

A package object is created when you use go install command on non-main packages. You will learn about main and non-main packages in packages lesson. Package object are also called as cached objects or cached packages.

bin

A Go program can either meant to be used as utility inside a package or to perform some operation. We have seen packages and where they reside.

A Go program that is meant to perform some operation like make a network request or write something to a file needs to be compiled first so that your machine can understand the instructions. When you run go run hello.go command, Go compiler first compiles the hello.go file and then executes the resultant binary code.

You can output a binary file from a Go program or package using go build <package-name> (main package) or go build program/path.go command. This will create a binary file in the current directory.

The bin directory contains the same binary executable files. These files are created by go install commands. go install command runs go build command internally and then outputs these files to the bin directory.

Generally, this directory is in the executable path of the system. Hence all the programs inside this directory are executable from the terminal.

go install command also creates package objects of any imported packages inside currently compiling Go program. Learn more about go build vs go install commands from here.

GOBIN is another environment variable that Go uses to put binary files created using go install command. By default, GOBIN is $GOPATH/bin but you can change it to whatever directory you like.

Summing it up

The motivation behind having a Go workspace is to easily manage your projects, dependencies, and distributions. Switching Go workspaces should be easy, hence I generally create one Go workspace per project and temporarily set $GOPATH environment variable to quickly change workspaces.

1. Set up environment variables

export GOPATH=/Users/Uday.Hiwarale/uday-gh/go_workspaces/main\
export GOBIN=$GOPATH/binPATH=$PATH:$GOPATH:$GOBIN\
export PATH

Setting GOBIN environment variable is not necessary, but since bin directory of a workspace will be in our PATH, it’s a good idea to set it for simplicity.

2. Make sure, $GOPATH and $GOBIN is set

As discussed, there is no need to set GOROOT environment variables as we are using the default installation directory (on macOS = /usr/local/go).

You can also use go env GOROOT or go env GOPATH command to check currently interprated Go environment variable.

3. Installing 3rd party package

This command will pull source code from the GitHub repository and clone it inside $GOPATH/src. This will also download other dependency packages of the gorm and install them under src directory.

After package and dependencies are downloaded, Go will compile the package and create a single package object file in $GOPATH/pkg directory under the same directory structure of the package.

4. Create binaries

It doesn’t matter, from where you execute go install shape command, Go knows where shape package is (from GOPATH environment variable).

Using this command, a binary file is generated inside bin directory with the name of the package. Since this bin directory is in our PATH, we can execute this binary file just by its filename as the command.

#golang #installation