Create Your First Golang App
Tags: go, softwaredevelopment
Published: 2020-05-26 05:50:15

---
title: Create Your First Golang App
published: true
date: 2020-05-26 01:50:00 EDT
tags: Golang,SoftwareDevelopment,Go
canonical_url: https://hackersandslackers.com/create-your-first-golang-app/
---

 ![Create Your First Golang App](https://hackersandslackers-cdn.storage.googleapis.com/2020/05/golang-gettingstarted.jpg)

To be human is to be an unwilling passenger in a winding, aimless journey we call life. Each of us has felt the eternal solidarity of time break apart as we are thrust into existence to navigate the tribulations of existing, left only to wonder what the point of it all is. Just as we become complacent in our respective existential struggles, an event of unspeakable force shakes the foundations of our reality: we fall in love.

Falling in love is as exhausting as it is enchanting. Our lifespans only have the willing capacity to fall in love a finite number of times, if at all. This realization is responsible for making us wary of falling in love in the first place, as well as zealously defending the love we've found against potential intruders. I'm one to advocate for an opposite conclusion. As difficult, scary, or time-consuming as love may be, I argue that a life that has discovered love on multiple occasions is a life well-lived. If that makes me a _slut_, so be it: I am a slut for programming languages.

I've proudly maintained a long-term loving commitment to Python, as well as a complicated affair with JavaScript. Still, even this promiscuous lifestyle can leave one yearning for a kind of love that only a statically-typed language can deliver. As our relationships transition from scripting honeymoons to mature enterprise-level endeavors, it's natural to second-guess our choices. Why endure the overhead of a dynamically typed language when we end up annotating types with [MyPy](http://mypy-lang.org/)? Could there be validity in arguments that claim our language of choice is "slow?" And do we really think we can put up with baggage known as the [GIL](https://wiki.python.org/moin/GlobalInterpreterLock) till death do us part?

If this all seems like a roundabout way to announce that I've been fooling around with Golang, that's because it absolutely is. I don't suspect that many people are willing or capable of leaving their comfort zones to partake in a journey of this magnitude. For the rest of you, I'd like to welcome you by my side for a short moment in our lives to explore the unexplored. Who knows, perhaps you'll even find love along the way.

## Installation and Setup

Installing on OSX is simple thanks to Homebrew:

```shell
$ brew update
$ brew install golang
```
<figcaption>Install Golang via Homebrew</figcaption>
### GOPATH vs GOROOT

Installing Golang via Homebrew automatically generates two directories critical to running Go:

- **GOROOT** ( `/usr/local/go` ): The Go "root" directory contains Go's source code. Homebrew will automatically register this path for you; there's little reason to mess around in here unless you're a Go contributor or if you're attempting to run multiple versions of Go.
- **GOPATH** ( `/Users/toddbirchard/go` ): Unlike most programming languages, Go takes an opinionated stance that all projects and dependencies of the language should exist in a single directory known as the _GOPATH_. Any time we develop a Go project or install a third-party module, the actions taken ultimately happen inside this directory.

To make sure OSX recognizes our   **GOPATH** , we'll have to add it to our shell's startup script. Open your **.bashrc** , **.zshrc** , or whatever it is you use:

```shell
$ vim ~/.zshrc
```
<figcaption>Modify shell script</figcaption>

We're going to add the **/go** base directory, as well as the subdirectory **/go/bin** :

```shell
export GOPATH=/Users/toddbirchard/go
export PATH=$PATH:$GOPATH
export PATH=$PATH:$GOPATH/bin
```
<figcaption>Add GOPATH to your PATH</figcaption>

Save this and reload your shell script:

```shell
. ~/.zshrc
```
<figcaption>Active changes</figcaption>

Let's make sure everything went as planned:

```shell
$ go version
>> go version go1.14.2 darwin/amd64
```
<figcaption>Verify Installation</figcaption>

And as a last bit of due diligence, let's confirm that our **GOPATH** is being recognized correctly:

```shell
$ go env GOPATH
>> /Users/toddbirchard/go
```
<figcaption>Verify GOPATH</figcaption>

As an aside, `go` is Golang's CLI which is essential for compiling, formatting, and running Go code, as well as installing _modules_ (we'll get to those in a sec). Try running `go help` to get acquainted.

## Anatomy of GOPATH

Golang's **GOPATH** is a directory where all your Go code and project dependencies live. The `go` CLI actually has a built-in command `$ go help gopath` which explains this quite well:

> The Go path is used to resolve import statements.  
> It is implemented by and documented in the go/build package.  
> The GOPATH environment variable lists places to look for Go code.

Similar to how Python looks for imported libraries in the Python path, Go searches the **GOPATH** for the same. A notable difference between Python and Go paths is that Go expects all your Go projects to live within the GOPATH, specifically **/go/src**. Contrast this with Python where projects can live anywhere.

The GOPATH directory is made up of 3 subdirectories:

```shell
/go
├── /bin
├── /pkg
└── /src
```
<figcaption>Structure of our GOPATH.</figcaption>

`$ go help gopath` explains the purpose of each of these directories.

**src:**

> The src directory holds source code. The path below src determines the import path or executable name.

**pkg:**

> The pkg directory holds installed package objects.  
> As in the Go tree, each target operating system and architecture pair has its own subdirectory of pkg (pkg/GOOS\_GOARCH).

**bin:**

> The bin directory holds compiled commands.  
> Each command is named for its source directory, but only the final element, not the entire path.

In short, your personal source code belongs in **/src** , installed third-party packages will live in **/pkg** , and third-party commands which extend the `go` CLI will live in **/bin**. To give an example, here's what my path looks like:

```shell
/go
├── /bin
│   ├── golint
│   └── tour
├── /pkg
│   ├── /darwin_amd64
│   │   ├── github.com
│   │   ├── go-pandas.a
│   │   ├── golangwebsite
│   │   └── hustlers
│   ├── /mod
│   │   ├── /cache
│   │   ├── /cloud.google.com
│   │   │   └── go@v0.57.0
│   │   ├── /github.com
│   │   │   ├── /google
│   │   │   │   └── go-cmp@v0.4.0
│   │   │   ├── /gorilla
│   │   │   │   └── mux@v1.7.4
│   │   │   ├── /mattn
│   │   │   │   └── go-runewidth@v0.0.7
│   │   │   ├── /olekukonko
│   │   │   │   └── tablewriter@v0.0.4
│   │   │   └── /rocketlaunchr
│   │   │       └── dataframe-go@v0.0.0-20200520082355-50e589cfde42
│   │   └── golang.org
│   └── /sumdb
│       └── sum.golang.org
└── /src
    ├── /golang-helloworld
    │   ├── README.md
    │   ├── go.mod
    │   ├── go.sum
    │   ├── golang-helloworld
    │   └── main.go
    ├── /golang.org
    │   └── x
    └── /hustlers
        ├── README.md
        ├── go.mod
        ├── go.sum
        ├── hustlers
        ├── main.go
        ├── main_test.go
        ├── static
        ├── templates
        └── vendor
```
<figcaption>My GOPATH.</figcaption>

We should be able to break this down quite easily.

- **/bin** contains two Go commands I installed previously. [golint](https://github.com/golang/lint) is a third-party linter for Go, and "tour" is a local version of the official [Tour of Go](https://tour.golang.org/welcome/1) walkthrough to help Go newcomers learn their way around the language (I highly recommend completing this, btw).
- **/pkg** contains the packages I've installed. Pay special attention to _/pkg/mod_, where you can see I've installed several packages from Github under the_/github.com_ directory. These packages include [dataframe-go](https://github.com/rocketlaunchr/dataframe-go), which is a Go implementation of Pandas-like DataFrames, as well as [mux](https://github.com/gorilla/mux), which is an HTTP router that we're going to use in our first hello-world project.
- **/src** has three projects I've worked on already. _golang-helloworld_ is the project we're about to create in this tutorial.

## Golang Terminology

Before we get to coding, let's brush up on some basic Go vocabulary:

- **Packages**: Go programs are made up of "packages," which mirror packaging concepts in other programming languages (think _modules_ in Python or _packages_ in Java). Every Golang program contains a package called **main**, which serves as the project's entry point.
- **Modules**: Go modules are third-party libraries installed by Go. Modules are essentially projects which have been published for general use as dependencies in your projects.
- **Vendors**: This is where things get interesting. While modules can be installed to the _/pkg/mod_ directory for global use, source projects can contain their _own_ versions of these modules to avoid clashing dependency versions between projects (this is not dissimilar to Python virtual environments). While not required, you can choose to keep module versions project-specific (we will do this in our example).

## Creating a Hello World App

Enough chit-chat, let's make our first Go project. We start with creating our project's directory in the **/go/src** directory:

```shell
$ cd $GOPATH/src
$ mkdir golang-helloworld
$ cd golang-helloworld
```

While inside our new project directory, we're now going to initialize our project as a Go _module._ This means anybody will be able to install our Go code off Github if they so choose. I know I'm going to save my repo to [github.com/hackersandslackers/golang-helloworld](https://hackersandslackers.app/p/eecb7ecb-860f-4acd-a943-32a0350c6017/github.com/hackersandslackers/golang-helloworld), so we run the following:

```shell
$ go mod init github.com/hackersandslackers/golang-helloworld
>> go: creating new go.mod: module github.com/hackersandslackers/golang-helloworld
```
<figcaption>Creating a Go module.</figcaption>

The moment this is done, a new file will appear in your directory called **go.mod**. Check out the contents using `$ cat go.mod` to see what this initializes with:

```shell
module github.com/hackersandslackers/golang-helloworld
  
go 1.14
```
<figcaption>go.mod</figcaption>

Pretty simple stuff so far! **go.mod** contains information about our module for others, such as the module name and Go version it is intended for. As we install dependencies for our project, these dependencies and their respective versions will be stored here.

### main.go

As mentioned, every Go project's entry point is a file called **main.go**. We're going to create the most simple **main.go** file imaginable: a script which outputs `"Hello, world."`:

```go
package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}
```
<figcaption>main.go</figcaption>

Now remember: since Go is a compiled language, we need to _build_ our project before we can run it. I know the extra effort is nearly unbearable, but things are about to pay off as you witness the fruits of your labor:

```shell
$ go build
$ go run main.go
>> Hello, world.
```
<figcaption>Build and run your module.</figcaption>

_WE DID IT!_ We've just created our first "hello world" app in Go. Your project structure should now look something like this:

```shell
/golang-helloworld
├── go.mod
├── golang-helloworld
└── main.go
```
<figcaption>Our project so far.</figcaption>

The newly created **golang-helloworld** file is the compiled executable which is created each time we run `$ go build`. Each time we make changes to our source code, we should run `$ go build` again to rebuild this executable with our changes.

### Bonus: Code Formatting

A nifty tool that comes out-of-the-box in Go is a code formatter to clean up any ugly indents and such in your source. Try messing up the indents in **main.go** and run the following:

```shell
$ go fmt
>> main.go
```
<figcaption>Formatting source code.</figcaption>

This should fix all the ugly formatting in the file names in outputs, in our case **main.go**.

## Create a Web App 

If we were to leave off with a stupid program that prints `"Hello, world!"`, I'd be doing you a disservice. While we've set up Golang successfully, we haven't learned much about creating anything useful yet. It's time for us to kick things up a notch by making our app a web app which can be served from a browser.

### Installing our First Dependency

To serve Go code via a web server, we're going to leverage the highly popular [gorilla/mux](https://github.com/gorilla/mux) module: a lightweight request router and dispatcher for matching incoming requests to their respective handler.

We're going to install this by running `$ go get` followed by `$ go install`:

```shell
$ go get -u github.com/gorilla/mux
$ go install github.com/gorilla/mux 
```
<figcaption>Install a dependency.</figcaption>

`go get` installs the source for **gorilla/mux** to our **/go/bin** directory. The `-u` flag we pass is an "update" flag, which we use to grab the latest version just in case.

Let's see how **go.mod** was affected by running `$ cat go.mod`:

```shell
module github.com/hackersandslackers/golang-helloworld
  
go 1.14

require github.com/gorilla/mux v1.7.4
```
<figcaption>go.mod</figcaption>

As promised, our module dependency has now been added to **go.mod** along with the proper version number. Now we can import and use `"github.com/gorilla/mux"` to help us build a project!

We can also use `$ go mod vendor` to build this dependency in our **/vendors** folder to keep it local to our project.

Here's a wall of code which turns our **hello world** app into a web app:

```go
package main

import (
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"time"
	"io"
)

func handler(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello, world!\n")
}

// Route declaration
func router() *mux.Router {
	r := mux.NewRouter()
	r.HandleFunc("/", handler)
	return r
}

// Initiate web server
func main() {
	router := router()
	srv := &http.Server{
		Handler: router,
		Addr:    "127.0.0.1:9100",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}

	log.Fatal(srv.ListenAndServe())
}
```
<figcaption>main.go</figcaption>

Our functions are `main()`, `router()`, and `handler()`, which get executed in that order.

### main()

`main()` sets up an HTTP server to be served locally on port **9100** , with a couple read & write timeouts set as a form of best practice. Our server doesn't do much on its own without any routes to resolve. That's where our `router()` function comes in.

### router()

We initialize a "router" by created variable **r** with `r := mux.NewRouter()`. From there we can set as many routes as we'd like with the following syntax:

```go
r.HandleFunc([URL_ROUTE], [FUNCTION_TO_EXECUTE])
```
<figcaption>Setting a route with mux.</figcaption>

`HandleFunc()` is a built-in method to resolve URL routes. The first parameter is the target URL, and the second is the name of a function to be executed when a user requests said route. We only specify a single route in our example, but we could theoretically set as many as we'd like, for example:

```go
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/about", aboutHandler)
r.HandleFunc("/contact", contactHandler)
return r
```
<figcaption>Example of setting multiple routes.</figcaption>
### handler()

Mux handler functions always accept two parameters by default, which essentially resolve to **output** and **input**. `w http.ResponseWriter` expects a parameter named **w** with the type **http.ResponseWriter**, which is what we return to render something for the end-user. `r *http.Request` contains information about the user's request, saved to a parameter named **r**.

We're keeping things simple(ish) today, so we'll settle for our route to simple output a "hello world" message for our route:

```go
io.WriteString(w, "Hello, world!\n")
```
<figcaption>Output a string.</figcaption>

Rebuild and run our project with `$ go build` and `$ go run main.go`. Now try visiting **127.0.0.1:9100** in your browser:

![Create Your First Golang App](https://hackersandslackers-cdn.storage.googleapis.com/2020/05/golang-helloworld.jpg)<figcaption>Our live Go app.</figcaption>

And there you have it, lovebirds.

## Best Practices

Before I leave to give you and your new favorite Gopher some private time, there's some very low-hanging fruit worth picking in an intro tutorial. This won't last long.

### "Exported" Functions (AKA: Public Versus Private)

Nearly every programming language has the concept of "private" versus "public" functions. Go has this concept as well regarding shared functions between packages. Functions that are "shared" are referred to as "exported functions" (sup JavaScript).

A name is exported if it begins with a capital letter. Our **hello world** example consisted solely of private functions (which makes sense, as we only had a single package). If we wanted to make our `router()` function accessible by other packages, we'd simply need to rename this to `Router()`.

### Type Declaration

Go expects that **variables** , incoming function **parameters** , and **function return values** to have declared types. In the below example, the function `add()` accepts two integers and adds them, which undoubtedly results in an integer:

```go
func add(x int, y int) int {
	return x + y
}
```
<figcaption>Setting types for incoming function parameters.</figcaption>

Variables are set using the same syntax as function parameters, with the variable name coming first:

```go
var x int = 0
```
<figcaption>Setting a single integer variable</figcaption>

There's also a shorthand way of setting multiple variables of the same type by separating variable names by commas. In this case, variables `x`, `y`, and `z` are set as integers with no assigned values:

```go
var x, y, z int
```
<figcaption>Creating 3 variables each sharing the <code>int</code> type.</figcaption>
### Short Assignment Statements

A very cool feature of Go is the `:=` operator. The "short assignment" operator can be used to set multiple variables at once _with implicit types_. That means Go will resolve the type of each variable on its own based on the value assigned without the need for explicit type declaration. The below example creates three variables, where `x` and `y` are resolved as booleans, and `z` is resolved as a string:

```go
func main() {
    x, y, z := true, false, "no!"
}
```
<figcaption>Implicitly set variable types with the <code>:=</code> operator.</figcaption>
### Constants

The last noteworthy nugget is the presence of **constants** in Go. While there's nothing unique about Go supporting constants, it's a breath of fresh air for Pythonistas who may be nostalgic about having the ability to do the following:

```go
const Website = "hackersandslackers.com"
```

## Happily Ever After?

Whether or not you hop on the Go train is a question of where your heart lies. While I'll continue using Python for the majority of what I do, it's nice to leave the Mrs. at home once in a while _(inb4 this misogynistic analogy ruins me)_ to fool around building quick endpoints in a statically-typed language _which isn't Java_. Have I ever mentioned how much [I hate Oracle](https://twitter.com/ToddRBirchard/status/1088315897847209985)? Like, how much I [_really_ hate them](https://twitter.com/ToddRBirchard/status/1088682663282642946)? No? Perhaps another time.

Anyway, get on with it then. The repository for what we've created today is up on Github here:

https://github.com/hackersandslackers/golang-helloworld