Go Crash Course

Want to write Go quickly and already have some experience in other languages? This post is for you!

This post is essentially a cleaned-up version of my notes of The Little Go Book with some additional clarifications I found helpful. If you have the time, I would highly recommend reading The Little Go Book instead of this 😅

Getting Started

To get Go (a.k.a. GoLang for googlability) code running on your computer, follow the official getting started guide. It boils down to:

  1. Download and install the Go CLI tool
  2. In a new folder, run go mod init github.com/yourUsername/yourModuleName
  3. Make a file hello.go and write some code, e.g.
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
  1. Run go run . to build and run the program.

How Go organizes dependencies

Go calls each dependency/application a “module”. Each module can contain one or more “packages”, which are just logical groups of source code files (essentially namespaces). For example, the module golang.org/x/net has a bunch of useful networking functions, grouped into packages like “net/html”, “net/http2”, etc. You add new dependencies to a module to your application by running go get your/dependency/moduleName.

Running go mod init your/module/name generates a new module with that name. If you plan to publish this module online for others to download, the name must be the path to where they can download it. For example, running go get github.com/fatih/color downloads the module at that URL. If you don’t intend to use your module as a dependency, you can name it whatever you want.

To be overly specific, running go get github.com/fatih/color makes a GET request to https://proxy.golang.org/github.com/fatih/color or - if it’s the first time it’s been queried - github.com/fatih/color?go-get=1 for information on where the actual repo is. It then downloads it from that url to the location set by your computer’s GOMODCACHE environment variable. On windows, this is C:\Users\YourUsername\go\pkg\mod. It can then be used from there inside any module on your computer.

In the example code above the package specified was named main, which tells Go to make it into a binary when you run go run .. Libraries usually don’t have a main package.

Rundown of Go

I’ll go through what I think are the more important parts of Go from the perspective of someone coming from, say, JS or Typescript.

type Vertex struct {
	X int
	Y int
}

// Add a function to the struct:
func (v *Vertex) MyVertexFunc() {...}
// Use a pointer in the first parenthesis if you need to modify the struct,
//use a regular reference otherwise. See: https://stackoverflow.com/questions/25382073/defining-golang-struct-function-using-pointer-or-not
...
myVertex := Vertex{100,200}
myDefaultVertex := Vertex{} // Any empty spots fill the parameters with the default, in this case, 0s.
...
myVertexXVal := myVertex.X // 100
myVertexFuncVal := myVertex.MyVertexFunc()
letters := []string{"a", "b", "c", "d"}
s := make([]string, 5)
// s == []byte{0, 0, 0, 0, 0}
s = append(s, "new", "elements", "to", "add")
myMap := make(map[string]int) // key is string, value is int
myMap["route"] = 66
j := myMap["nonExistent string"] // j == ""
i, ok := myMap["nonExistent string"] // ok == false, i == ""
delete(myMap, "route")
for key, value := range myMap { ... }
type Logger interface {
RequiredFunc(funcParam string)
} // Interfaces are only a collection of methods, not parameters.
func process(varName varType) returnType { ... }
defer func() {
	if r := recover(); r != nil {
		fmt.Println("Recovered. Error:\n", r)
	}
}()
if err := process(); err != nil {
return err
}
func add(a interface{}) {...}
type add func(a int, b int) int

func main() {
	var a add = func(a int, b int) int {
		return a + b
	}
	s := a(5, 6)
	fmt.Println("Sum", s)
}
// Waiting for space to put into the channel
for { // infinite loop if have a stream of data
	select {
	case c<- rand.Int():
		//optional code here
	default:
		// what to do when the channel is full and you're dropping the data. If no default is given, select blocks the main thread.
	}
}
...
// Waiting for data to come into the channel
for i := 0; i < 2; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        }
}

That’s it for the introduction to Go. The next post should hopefully be a crash course in writing web servers in Go, following the very helpful Let’s Go book.