Some Go basics to get you started, Part II: Where does your code go?

One of the more contentious issues with Go, although this is less of an issue now, is the location of your Go source. All your code goes in to the Go Path, which is your workspace. If you are used to dotNET apps, or just about any other language environment, then this is quite a hard thing to get over. I still find this one of the more frustrating experiences with Go.

Your code will sit under this Go Path location. In newer versions of Go you no longer need to set the GOPATH environment variable explicitly, which was a requirement before. Instead, ~/go is the default location. If you want it anywhere else, then you need to use the GOPATH variable. Since my code rarely sits in my user folder (at least at work), I set the GOPATH variable. I will assume that you know some terminal/command line stuff, so this is what my variables look like on my personal computer:

$ env | grep GO
GOPATH=/Users/brian/go

I didn’t really need the GOPATH on my home Mac since it’s in the default location, but habit has left it there. The location could be anywhere though. At work it’s in “D:\source\go”. So there my GOPATH is D:\source\go

Now that you have set your GOPATH (or left it as default), there’s a strict structure under here:

$ tree -L 1
.
├── bin
├── pkg
└── src

The bin folder contains all the compiled executables for your code and packages. For example, and we will look at Cobra later on, when you install Cobra using the standard install method it drops a Cobra executable in the bin folder. Add this to your PATH environment variable. That way the executables will be available from anywhere on your system.

The pkg folder is where all packages’ binaries are installed to. They are pre-compiled there for optimised compile times. Each architecture that you are targeting will get a sub folder under the pkg folder:

$ tree pkg/ -L 1
pkg/
├── darwin_amd64

I only compile for the Mac on this machine, so that’s all that sits here. Reading between the lines, yes, you can compile for other architectures from any machine.

The src folder is where you do all your magic and is also where all the installed packages’ source code lives. If all your code is in a source control repository, then your code sits under various folders depending on where your code is hosted (github vs bitbucket for example). Here’s a tree of my src folder at the moment:

$ tree src/ -L 1
src/
├── bitbucket.com
├── github.com
├── golang.org
├── gopkg.in
└── sourcegraph.com

This helps keep all source code from various locations nicely tucked away. Since I know that under bitbucket.com, my user name is brianj-za, then all my code sits here:

$ tree src/bitbucket.com/brianj-za/ -L 1
src/bitbucket.com/brianj-za/
├── cli
├── cli1
├── cs-fundamentals
├── example
├── hash
├── package-test
├── project-euler

And that’s where your code should live. Early on I was placing my code directly under the src folder. It’s not actually the end of the world if you do, particularly if you don’t have a GitHub or BitBucket repository (or some repository at your work or school). However, if you are using a source control repository, then use that as a sub folder and make it a habit.

I hope the above makes sense. Don’t fight this opinion, as it will not help you. However, if I’m honest, it is probably the one experience in Go I am not a fan of, and specifically because I write systems in more than one language or framework. I cannot keep all my source code close together as my dotNET applications may fall under d:\source\digit.mycompany\MyProject, but my Go microservice ends up under d:\source\go\src\digit.mycompany\brianj\MyProject\MicroService1. They’re not even close to each other. I hope one day they will fix this. I could put my .NET code under my GOPATH but this feels messy.

Launching my application

To get started let’s at least see how we run our hello world application. Your application should be under your GOPATH src folder somewhere. Mine is here:

$ pwd
/Users/brian/go/src/bitbucket.com/brianj-za/hello-world

You can create this folder as follows (assuming you have a GOPATH variable):

$ mkdir -p $GOPATH/src/bitbucket.com/brianj-za/hello-world

Or without the GOPATH variable (in bash, for Windows you will need to do something different):

$ mkdir -p ~/go/src/bitbucket.com/brianj-za/hello-world

I need to open a terminal (or command line) to the location above. Here are the contents of the folder in my case, you can create the file manually:

$ ls
main.go

Here’s what is in my main.go file, copy this in to your file:

package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}

So how do I run my application? You use the go toolset to do so. You could either just run the main.go file like so:

$ go run main.go
Hello, world.

Or you could build your application and run the executable:

$ go build
$ ./hello-world
Hello, world.

Or, lastly, you could install your application and run it that way. This is not recommended for everyday development though:

$ go install
$ hello-world
Hello, world.

The install option puts your executable in the GOPATH bin folder. This is great if you write utilities that you need to access on your machine, which I do. So this is my way of installing my app once it’s ready. You could just as easily copy the executable from go build to anywhere you like, since there’s no runtime requirement.

I encourage you to experiment with the Hello world application a bit to see what happens. Run the go run main.go (or go build) and see what happens. Try to break your build and see if you can fix the errors. If you come unstuck, just delete everything and paste the code above back in.