Go cheatsheet

2 minute read

Command Line

go build
go run
go test

Loop Syntax

for { // forever loop
}
for condition { 
}
for i, value := range slice { // works for maps too
}
for i:=0; i<N; i++ {
}

Slices Syntax

fibonacci := [10]int{0, 1, 1, 2, 3, 5, 8, 13, 21, 34}
var slice []int = fibonacci[3:7] // takes indexes 3, 4, 5, 6
slice2 := make([]int, 5)
fmt.Println(slice) // [2 3 5 8]
slice[0] = 1337        // note: slices are references!
fmt.Println(fibonacci) // [0, 1, 1, 1337, 3, 5, 8, 13, 21, 34]
slice = append(slice, element, ...)

Map syntax

myMap := make(map[string]float32)
myMap["Accel"] = 9.81
// (0.0, false) if no "gyro" field; (val, true) otherwise
rate, has_field := myMap["Gyro"] 

Object Oriented-like things

Adding methods to structs

  • (v Vector3) is known as a receiver, it copies the data
  • (v *Vector3) is a pointer receiver, and is useful when we will modify the struct
type Vector3 struct {
  X, Y, Z float64
}
func (v *Vector3) Norm() float64 {
  return math.Sqrt(v.X*v.X + v.Y*v.Y + v.Z*v.Z)
}
func (v *Vector3) Add(a float64) {
  v.X += a
  v.Y += a
  v.Z += a
}
distance = Vector3{1.0, 2.0, 3.0}.Norm()

Interfaces

Interface implementation is implicit, if a struct has the interface’s method signatures, it implements the interface.

type Vector interface {
  Norm() float64
  Add() float64
}

var v Vector
v3 := Vector3{0.0, 0.0, 0.0}
v := &v3

Type assertions allow us to check the underlying type of something whcih meets an interface:

val, ok := v.(Vector3) // ok = true
val, ok := v.(int32)   // ok = false

Type switches:

switch v := i.(type) {
case Vector3:
  // ...
case Vector2:
  // ...
default:
  // ...
}

Concurrency

Run a go routine

func doSomething() {
}
go doSomething()

Channels

ch := make(chan float64)
ch := make(chan float64, 100) // buffer 100 entries
ch <- value // send to channel
value := <- ch  // receive from channel
func doSomething(ch chan float64)
close(ch) // closes the channel
value, ok := <- ch // ok = false if ch is closed
// loop until the channel closes 
for value  := range ch {
}
select { // blocks until one of its case can be run
case ch1 <- x: // runs when we can load data into c
case <-ch2:    // runs when ch2 has data
}
select { // non-blocking
case ch1 <- x: // runs when we can load data into c
case <-ch2:    // runs when ch2 has data
default:       // runs if nothing is ready
}
time.Tick(Duration)  // periodic channel
time.After(Duration) // periodic channel

Enums

Use iota:

type Commands int

const (
    Sit Commands = iota
    Fetch
    RollOver
)

This stack exchange answer details some more advanced techniques including bitfield enumeration.