Learn Go with Examples

I always wanted to spend more time learning Go. After a long break I finally got a chance to take it up seriously. The best lesson for me was to not learn it from scratch like I did with my first programming language. I learned a few basics first from the official documentation and Learn Go Programming - Golang Tutorial for Beginners. Since I'm already well experienced in writing good sized code bases in Python, I decided to dive right in and implement a project on top of Azure SDK. One big advantage of this approach was that I could learn from working examples in Azure documentation and build my knowledge over time. The second advantage was that I was building something useful right away that kept my motivation up; I wasn't building some abstract thing where I also needed to conjure a problem and solution.

This post is still a work in progress. I'll update it as I go along.

Companion git Repo

This blog post has a companion git repo: https://github.com/aikchar/learngo. There are multiple checkpoints in this post. Each checkpoint has a corresponding branch in the repo. As you follow along the post you can checkout the checkpoint branch and inspect it.

Initial Setup

The best place to start:

Incremental Learning

Some tricks I use as I learn Go, its type system, etc.

I use Visual Studio Code with the Go extension. By hovering the mouse over a function from a library, such as Azure SDK, I can click the documentation link that pops up right above it. It's a life saver.

Visual Studio Code also automatically add the import line as soon as I start using the function from that library. It's really neat.

When I'm unsure of the data type, I print it with fmt.Printf("%s", myvar). The compiler yells at me that the data type is not a string and outputs the real data type.

Organize Code

I'm still learning how to do this. This is what I know so far.

Figure out the "namespace" and name of the project. For example, my namespace is github.com/aikchar and name is learngo. The full name, or the import path, is github.com/aikchar/learngo. Create a directory of the same name to make things easier.

$ mkdir -p ~/repos/github.com/aikchar/learngo

I usually put my repos under ~/repos so that's what I did here. You can use whichever parent directory you prefer.

Create packages in sub-directories of the root directory. For example,

$ mkdir -p ~/repos/github.com/aikchar/learngo/mypkg1
$ mkdir -p ~/repos/github.com/aikchar/learngo/mypkg2

Create your main file, with package main and func main(), in the root directory. You don't have to call it main.go but it's easier to identify.

$ touch ~/repos/github.com/aikchar/learngo/main.go

From here on assume we're always in the ~/repos/github.com/aikchar/learngo directory unless otherwise stated.


Initialize your go.mod first.

$ go mod init github.com/aikchar/learngo

More information:


Change to your project's directory and fetch your first dependency. In my case it was the Azure SDK. I fetched two different authentication libraries below.

$ go get github.com/Azure/azure-sdk-for-go/sdk/azidentity  # Newer
$ go get github.com/Azure/go-autorest/autorest/azure/auth  # Older

If you already have the dependency downloaded in some other path, you can alias the official import path with your local path. This uses the replace keyword.

You can also vendor Azure SDK. It means that you maintain a copy of it in your own source tree. It removes the need to fetch it everytime you need to build your project on a new machine; it's always right there along with your code. It's optional so you decide if you want to do this.

$ go mod vendor

If you don't use a dependency in your code, you can remove depdencies automatically. This can be tricky because if you previously go get that dependency it will be removed from go.mod. Use this carefully. Most people use it before they commit their changes.

$ go mod tidy

Since we are not using any dependencies yet, let's remove Azure SDK. Run,

$ go mod tidy

More information:

main.go First Draft

Let's create a skeleton main.go.

$ vim main.go
package main
func main(){}

Here we'll also try go fmt for the first time. This will format our code according to community standards.

$ go fmt


Building is also easy.

$ go build

This will create a static binary with the same name as the parent directory. In my case it's learngo.

$ ls
go.mod  go.sum  learngo main.go

Checkpoint 1

This is our first checkpoint. You can clone https://github.com/aikchar/learngo and checkout branch cp-1.

$ git clone https://github.com/aikchar/learngo.git
$ git checkout -t origin/cp-1

I will not include binaries in the repo. For example, you won't see the learngo file.