Skip to content

Latest commit

 

History

History
778 lines (530 loc) · 10.9 KB

golang.md

File metadata and controls

778 lines (530 loc) · 10.9 KB
title date icon background tags categories intro
Golang
2020-12-17 13:51:44 -0800
icon-golang
bg-blue-400
Go
Programming
This cheat sheet provided basic syntax and methods to help you using [Golang](https://golang.org/).

Getting started {.cols-3}

Introduction

Hello world {.row-span-2}

hello.go {.file}

package main

import "fmt"

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

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

Or try it out in the Go repl, or A Tour of Go.

Variables

Variable declaration

var msg string
msg = "Hello"

Shortcut of above (Infers type)

msg := "Hello"

Constants

Constants can be character, string, boolean, or numeric values.

const Phi = 1.618

See: Constants

Basic types {.cols-3}

Strings

str := "Hello"

str := `Multiline
string`

Operators

// Outputs: 11
fmt.Println(len("Hello World"))

// Outputs: Hello
fmt.Println(string("Hello World"[0:5]))

// Outputs: Hello World
fmt.Println("Hello " + "World")

Strings are of type string.

Numbers

Typical types

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

Other types

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

Operators

// Outputs: 1 + 1 = 2
fmt.Println("1 + 1 =", 1.0 + 1.0)

- -
+ addition
- subtraction
* multiplication
/ division
% remainder

Slices have a dynamic size, unlike arrays.

Booleans

isTrue   := true
isFalse  := false

Operators

// Outputs: true
fmt.Println(true && true)

// Outputs: false
fmt.Println(true && false)

// Outputs: true
fmt.Println(true || true)

// Outputs: true
fmt.Println(true || false)

// Outputs: false
fmt.Println(!true)

Arrays {.row-span-2}

var a [2]string
a[0] = "Hello"
a[1] = "World"

// Outputs: Hello World
fmt.Println(a[0], a[1])

// Outputs: [Hello World]
fmt.Println(a)

primes := [6]int{2, 3, 5, 7, 11, 13}

// Outputs: [2 3 5 7 11 13]
fmt.Println(primes)

// Same as [:3], Outputs: [2 3 5]
fmt.Println(primes[0:3])

Arrays have a fixed size.

Pointers {.row-span-2}

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

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

See: Pointers

Type conversions

i := 90
f := float64(i)
u := uint(i)

// Will be equal to the character Z
s := string(i)

How to get int string?

i := 90

// need import "strconv"
s := strconv.Itoa(i)
fmt.Println(s) // Outputs: 90

See: Type conversions

Slices

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

Flow control {.cols-3}

Conditional

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

See: If

Statements in if

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

A condition in an if statement can be preceded with a statement before a ;. Variables declared by the statement are only in scope until the end of the if.

See: If with a short statement

Switch

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

  case "saturday":
    rest()

  default:
    work()
}

See: Switch

For loop

for count := 0; count <= 10; count++ {
  fmt.Println("My counter is at", count)
}

See: For loops

For-Range loop

entry := []string{"Jack","John","Jones"}
for i, val := range entry {
  fmt.Printf("At position %d, the character %s is present\n", i, val)
}

See: For-Range loops

While loop

n := 0
x := 42
for n != x {
  n := guess()
}

See: Go's "while"

Functions {.cols-3}

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 defining the return value names in the signature, a return (no args) will return variables with those names.

See: Named return values

Packages {.cols-3}

Packages

package hello

Every package file has to start with package.

Importing {.row-span-2}

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

Both are the same.

See: Importing

Exporting names

func Hello () {
  ···
}

Exported names begin with capital letters.

See: Exported names

Aliases

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

Concurrency {.cols-3}

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.

See: Goroutines, Channels

WaitGroup

import "sync"

func main() {
  var wg sync.WaitGroup
  
  for _, item := range itemList {
    // Increment WaitGroup Counter
    wg.Add(1)
    go doOperation(item)
  }
  // Wait for goroutines to finish
  wg.Wait()
  
}
func doOperation(item string) {
  defer wg.Done()
  // do operation on item
  // ...
}

A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. The goroutine calls wg.Done() when it finishes. See: WaitGroup

Closing channels

Closes a channel

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

Iterates across a channel until its closed

for i := range ch {
  ···
}

Closed if ok == false

v, ok := <- ch

See: Range and close

Buffered channels

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

Buffered channels limit the amount of messages it can keep.

See: Buffered channels

Error control {.cols-2}

Deferring functions {.row-span-2}

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

Lambdas are better suited for defer blocks.

func main() {
  var d = int64(0)
  defer func(d *int64) {
    fmt.Printf("& %v Unix Sec\n", *d)
  }(&d)
  fmt.Print("Done ")
  d = time.Now().Unix()
}

The defer func uses current value of d, unless we use a pointer to get final value at end of main.

Defer

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

Defers running a function until the surrounding function returns. The arguments are evaluated immediately, but the function call is not ran until later.

See: Defer, panic and recover

Structs {.cols-3}

Defining

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

See: Structs

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 put field names.

Pointers to structs

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

Doing v.X is the same as doing (*v).X, when v is a pointer.

Methods {.cols-2}

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 with receivers.

See: Methods

Mutation

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

By defining your receiver as a pointer (*Vertex), you can do mutations.

See: Pointer receivers

Interfaces {.cols-2}

A basic interface

type Shape interface {
  Area() float64
  Perimeter() float64
}

Struct

type Rectangle struct {
  Length, Width float64
}

Struct Rectangle implicitly implements interface Shape by implementing all of its methods.

Methods

func (r Rectangle) Area() float64 {
  return r.Length * r.Width
}

func (r Rectangle) Perimeter() float64 {
  return 2 * (r.Length + r.Width)
}

The methods defined in Shape are implemented in Rectangle.

Interface example

func main() {
  var r Shape = Rectangle{Length: 3, Width: 4}
  fmt.Printf("Type of r: %T, Area: %v, Perimeter: %v.", r, r.Area(), r.Perimeter())
}

References {.cols-2}

Official resources

Other links