You got a taste of Go in the Go tutorial introduction and decided to continue learning; great! let’s dive in a little deeper. This tutorial helps you install Go and a decent IDE to work in. Then we’ll look at the go command and build and run Go program. We’ll also learn about packages and modules, which are the essential building blocks for any Go project. Let’s go!
Install Go
Before you start, you need to have Go installed on your system. If you haven’t done so, first download and install Go for your system. There are roughly two ways to do so:
- Download and install an installer from the official site
- Use OS-specific packages (e.g., using
apt
oryum
on Linux distros)
I prefer option one on Windows since it gives me the latest version. I usually use the package manager on Linux because it automatically keeps Go up-to-date with bug fixes and such. Sometimes the OS package manager installs an ancient version. If so, you’re better off downloading Go from the official website.
To see which version of Go you just installed, keep reading!
Working on the command-line
One of the assumptions I’ll make is that you are familiar with using a command-line shell:
- On Windows, I suggest you use Powershell or git bash. I prefer the latter because I like creating small Bash scripts to automate things, and it’s nice if these scripts work on both Windows and Unix-like systems.
- On Linux, this is usually Bash or zsh
- On recent MacOS systems, it will be zsh by default unless you installed something else.
If you are not familiar with using such a shell, please take the time to learn about them now and return here once you did. I wrote an introduction to the Unix shell on Python Land, and I suggest reading it as well. Trust me when I say it’s time well spent!
How to check my Go version?
Once you have Go installed, open a shell to check its version using the following command:
go version
Code language: Bash (bash)
You can check the output against the latest version available on the official download page. If it’s anything below 1.16, please install the most recent version using an official installer. In 1.13, Go introduced modules, and we will start using them on this page. There have been several improvements since then, and you would be hindering yourself if you didn’t install the most recent version. I used Go 1.19 while writing this tutorial, so try to have at least that version.
Using an IDE (Visual Studio Code)
In addition to installing Go, you need an IDE (unless you’re the hardcore type that uses VIM or Emacs). I recommend only one IDE, and that is Visual Studio Code. Here are a few reasons why you might want to try it before anything else:
- It’s free and open source
- You can install it on Windows, MacOS, and Linux and sync your extensions (if you create an optional account)
- It has decent support for many programming languages, including Go, Python, Java, C#, etcetera. It’s a one-stop shop.
So go ahead and install VSCode if you haven’t already done so. Then install the Go extension (the most downloaded one, created by the Google team). That’s all you need to continue.
The Go Command
Go programmers make extensive use of one single command: go
. It can be used to run, test, and compile your go code. It also helps you fetch modules from the Internet. Let’s start by running our ‘Hello World’ program.
Running a single file
We’ll start with the simplest form of using Go: running a single .go
file, such as the hello.go
file from the Go tutorial introduction. For this, we can use the go run
command like so:
go run hello.go
Code language: Bash (bash)
Build and run a Go program
Each time you use go run
, your source code is compiled into a binary. This binary is then executed, after which it gets thrown away. That’s alright during development, but once your program is finished, you want to create a runnable binary (e.g., a .exe
on Windows). For this, you need to use the go build
command:
go build hello.go
Code language: Shell Session (shell)
On Windows, this results in an executable file called hello.exe
that you can run directly. On Linux and MacOS, it results in a file called hello
that you can run by entering ./hello
.
These are native, binary programs that are not dependent on anything else. You can share them with anyone using the same OS and system architecture. To run this executable, one does not need a Go installation.
Reduce the executable size
If we inspect the resulting executable, we can see it is quite large, especially when you compare it to compiled C code. On my Windows machine, the binary is almost 2MB. Most people won’t care, and rightfully so. It’s still way more efficient than, for example, needing a complete Java or Python installation to run your program.
So why is the binary this large? Go needs to include some stuff, like the garbage collector, but it also includes some unnecessary things you can strip. I wrote a blog post on reducing the Go executable size for those who care about file size. I’d say that anyone who creates programs to share with the world should go through the small effort of reducing their binary. If you’re building something for yourself or internal to your company, you might rightfully care less about it.
Packages
As we’ve learned in the Go tutorial introduction, Go code always resides in one or more files. These files, in turn, are always part of a package. A package is a directory on the filesystem containing a collection of related Go source code files. A package may contain one or more .go
files, each defining part of the package’s functionality. If and how you split your code into multiple files is up to you.
A package is a collection of related Go source code files in the same directory.
Each file needs to declare its package name at the top of the file. Once those conditions are met, each file in the package has access to all functions, variables, constants, and types defined in any of the files inside that package.
Why packages?
Packages are an important concept in Go, as they provide a way to organize and modularize your code. This makes it easier to reuse your code in other projects and also helps to prevent naming conflicts between different parts of your code.
Each Go package has a unique name. For example, the fmt
package that we’ve seen before has the package name fmt
. Go includes many built-in packages, such as the fmt
package, that you can use in your own Go programs. And, of course, we can also define our own packages.
Modules
Packages, in turn, are part of a module. A module is a collection of related Go packages.
Small projects may consist of a single package (main
), containing just one or only a few files. This package is, in turn, part of a module. We’ll see how to create a module shortly.
A module is a collection of related Go packages.
It’s easy to imagine how modules could contain multiple packages, though. Imagine writing the backend of an online poker game, for example. The poker backend could contain a package that implements the game logic, while a second package offers the HTTP API. This way, the game logic can be written independently from any other logic (the HTTP stuff).
There are multiple advantages to splitting up your code like this:
- The code is easier to test (manually or through so-called unit tests)
- The game logic can be reused easily; it’s not intertwined with HTTP API code. For example, you might also want to use it for a command-line poker game.
In fact, you might even want to put the game logic in its own Go module, so anyone with access to the module can fetch it and use it in their project. But I’m getting ahead of things now. Let’s first explore how to define a Go module.
The go.mod file
A Go module is defined by a go.mod
file. In such a file, we can specify the minimum Go version that this project requires and the exact versions of the dependencies that our program needs. When building your project, Go will automatically download and manage those dependencies.
Go modules were introduced in Go 1.11 to manage dependencies and ensure reproducible builds of Go programs. Before Go 1.11, Go relied on your code being put inside the GOPATH, an environment variable pointing to Go’s workdir. The old way of working had some limitations that were remediated by introducing modules. If you want to learn more about this subject, I recommend this wiki page.
You’ll still find a lot of documentation telling you to set your GOPATH. This is a sign of documentation written before Go modules became a thing. You might want to steer clear of books and tutorials that don’t mention modules. They can still be great for learning the language, but you might get confused because they’ll teach you the old way of working with dependencies.
GOPATH is still a thing
Despite modules taking over from working inside the GOPATH, the GOPATH environment variable still exists. It defaults to $HOME/go on Unix-like systems and %USERPROFILE%\go on Windows. I recommend not changing it, as it is used by Go to cache downloaded modules.
Defining a Go module
Now that we know about go.mod
files let’s create one ourselves. I’m assuming you have created a directory (called hello
, for example) in which you’ve placed the hello.go
file from the introduction. To turn this into a Go module, you use the following command:
go mod init example.org/hello
Code language: Python (python)
After running it, you should have a file with the following content:
module example.org/hello
go 1.19
Code language: Python (python)
This is the simplest form a Go module can take, but it will do for now.
I used the domain name example.org
in this module name. Go modules, especially those published on the Internet, are always prefixed with a domain name like that. If you have your own domain, you might want to use it. If your module is open-source and lives on GitHub, you should use a prefix like github.com/username/projectname
.
Building a module
Once you have created your go.mod
file, you can use the go
command to manage your module and its dependencies.
For example, when you enter go build
without arguments, Go will look for the file containing the main() function and main package. That file’s name will also be used for the output filename. So in our case, go build
will build an executable called hello.exe
or just hello
on Unix-like systems.
In addition, we can now use the go get
command to download external modules as well.
Getting external modules
Let’s conclude this article by using go get
to fetch an external module and using it in our module.
TO BE CONTINUED