Skip to content

Go Programming Language Cheat Sheet

Go (also known as Golang) is a statically typed, compiled language developed by Robert Griesemer, Rob Pike, and Ken Thompson at Google. Go syntax is similar to C, but it features memory safety, GC (garbage collection), structural typing, and CSP-style concurrency.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

Variables

Variable declaration

var msg string
msg = "Hello"

Short-hand

msg := "Hello"

Constants

const Phi = 1.618

Constants can be characters, strings, booleans, or numeric values.

Basic Types

Strings

str := "Hello"
str := `Multiline
string`

The type for strings is string.

Numbers

Typical types

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias for uint8)

Other types

var u uint = 7        // uint (unsigned)
var p float32 = 22.7  // 32-bit float

Pointers

func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
}
 
func getPointer () (myPointer *int) {
  a := 234
  return &a
}

Pointers point to a memory location of a variable. Go is fully garbage collected.

Arrays

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

Arrays have a fixed size.

Slices

slice := []int{2, 3, 4}
slice := []byte("Hello")

Unlike arrays, slices have a dynamic size.

Flow Control

Conditionals

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

Statement in if

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

An if statement can execute a simple statement before the conditional expression.

Switch

switch day {
  case "sunday":
    // cases don't "fall through" by default!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Functions

Lambdas

myfunc := func() bool {
  return x > 10000
}

Functions are first-class objects.

Multiple return types

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

Named return values

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

By naming the return values in the declaration, return (without arguments) will return the variables with those names.

Packages

Loading

import "fmt"
import "math/rand"
import (
  "fmt"        // gives fmt.Println
  "math/rand"  // gives rand.Intn
)

Both are the same.

Aliases

import r "math/rand"
 
r.Intn()

Exported Names

func Hello () {
  ···
}

Exported names start with a capital letter.

Packages

package hello

Every package file must start with a package statement.

Concurrency

Goroutines

func main() {
  // A "channel"
  ch := make(chan string)

  // Start concurrent routines
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Read 3 results
  // (Since our goroutines are concurrent,
  // the order isn't guaranteed!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

Channels are concurrency-safe communication objects used in goroutines.

Buffered Channels

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// all goroutines are asleep - deadlock!

Buffered channels limit the number of messages it can hold.

Closing Channels

Closes a channel

ch <- 1
ch <- 2
ch <- 3
close(ch)

Iterate a channel until it’s closed

for i := range ch {
  ···
}

Closed if ok == false

v, ok := <- ch

Defer & Panic

Defer

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

Defers the execution of a function until the surrounding function returns. The arguments are evaluated immediately, but the function call is not run until the end.

Defer with Lambdas

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

Lambdas are better for deferring blocks.

Structs

Definition

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

Literals

v := Vertex{X: 1, Y: 2}
// Field names can be omitted
v := Vertex{1, 2}
// Y is implicit
v := Vertex{X: 1}

You can also specify field names.

Pointers to Structs

v := &Vertex{1, 2}
v.X = 2

When v is a pointer, v.X and (*v).X are the same.

Methods

Receivers

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

There are no classes, but you can define functions on types using receivers.

Pointer Receivers

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// `v` is updated