Cheat Sheet for Golang

Golang

Summary

Hello World

1package main
2
3import "fmt"
4
5func main() {
6    fmt.Println("Hello Gophers!")
7}

Return to Summary

Go CLI Commands

 1# Compile & Run code
 2$ go run [file.go]
 3
 4# Compile
 5$ go build [file.go]
 6# Running compiled file
 7$ ./hello
 8
 9# Test packages
10$ go test [folder]
11
12# Install packages/modules
13$ go install [package]
14
15# List installed packages/modules
16$ go list
17
18# Update packages/modules
19$ go fix
20
21# Format package sources
22$ go fmt
23
24# See package documentation
25$ go doc [package]
26
27# Add dependencies and install
28$ go get [module]
29
30# See Go environment variables
31$ go env
32
33# See version
34$ go version

Return to Summary

Go Modules

  • Go projects are called modules
  • Each module has multiple packages
  • Each package should has a scoped functionality. Packages talk to each other to compose the code
  • A module needs at least one package, the main
  • The package main needs a entry function called main
1# Create Module
2$ go mod init [name]

Tip: By convention, modules names has the follow structure:

domain.com/user/module/package

Example: github.com/spf13/cobra

Return to Summary

Basic Types

Type Set of Values Values
bool boolean true/false
string array of characters needs to be inside ""
int integers 32 or 64 bit integer
int8 8-bit integers [ -128, 128 ]
int16 16-bit integers [ -32768, 32767]
int32 32-bit integers [ -2147483648, 2147483647]
int64 64-bit integers [ -9223372036854775808, 9223372036854775807 ]
uint8 8-bit unsigned integers [ 0, 255 ]
uint16 16-bit unsigned integers [ 0, 65535 ]
uint32 32-bit unsigned integers [ 0, 4294967295 ]
uint64 64-bit unsigned integers [ 0, 18446744073709551615 ]
float32 32-bit float
float64 64-bit float
complex64 32-bit float with real and imaginary parts
complex128 64-bit float with real and imaginary parts
byte sets of bits alias for uint8
rune Unicode characters alias for int32

Return to Summary

Variables

 1// Declaration
 2var value int
 3
 4// Initialization
 5value = 10
 6
 7// Declaration + Initialization + Type inference
 8var isActive = true
 9
10// Short declaration (only inside functions)
11text := "Hello"
12
13// Multi declaration
14var i, j, k = 1, 2, 3
15
16// Variable not initialized = Zero values
17// Numeric: 0
18// Boolean: false
19// String: ""
20// Special value: nil (same as null)
21
22var number int // 0
23var text string // ""
24var boolean bool // false
25
26// Type conversions
27// T(v) converts v to type T
28
29i := 1.234 // float
30int(i) // 1
31
32// Constants
33const pi = 3.1415

Operators

Return to Summary

Arithmetic Operators

Symbol Operation Valid Types
+ Sum integers, floats, complex values, strings
- Difference integers, floats, complex values
* Product integers, floats, complex values
/ Quotient integers, floats, complex values
% Remainder integers
& Bitwise AND integers
` ` Bitwise OR
^ Bitwise XOR integers
&^ Bit clear (AND NOT) integers
<< Left shift integer « unsigned integer
>> Right shift integer » unsigned integer

Comparison Operators

Symbol Operation
== Equal
!= Not equal
< Less
<= Less or equal
> Greater
>= Greater or equal

Logical Operators

Symbol Operation
&& Conditional AND
`
! NOT

Return to Summary

Conditional Statements

 1// If / Else
 2i := 1
 3
 4if i > 0 {
 5    // Condition is True! i is greater than zero
 6} else {
 7    // Condition is False! i is lower or equal to zero
 8}
 9
10// Else if
11i := 1
12
13if i > 0 {
14    // Condition is True! i is greater than zero
15} else if i > 0 && i < 2 {
16    // Condition is True! i greater than zero and lower than two
17} else if i > 1 && i < 4 {
18    // Condition is True! i greater than one and lower than four
19} else {
20    // None of the above conditions is True, so it falls here
21}
22
23// If with short statements
24i := 2.567
25
26if j := int(i); j == 2 {
27    // Condition is True! j, the integer value of i, is equal to two
28} else {
29    // Condition is False! j, the integer value of i, is not equal to two
30}
31
32// Switch
33text := 'hey'
34
35switch text {
36    case 'hey':
37        // 'Hello!'
38    case 'bye':
39        // 'Byee'
40    default:
41        // 'Ok'
42}
43
44// Switch without condition
45value := 5
46
47switch {
48    case value < 2:
49        // 'Hello!'
50    case value >= 2 && value < 6:
51        // 'Byee'
52    default:
53        // 'Ok'
54}

Return to Summary

Loops

 1// Golang only has the for loop
 2for i := 0; i < 10; i++ {
 3    // i
 4}
 5
 6// The first and third parameters are ommitable
 7// For as a while
 8i := 0;
 9
10for i < 10 {
11    i++
12}
13
14// Forever loop
15for {
16
17}

Return to Summary

Arrays

 1// Declaration with specified size
 2var array [3]string
 3array[0] = "Hello"
 4array[1] = "Golang"
 5array[2] = "World"
 6
 7// Declaration and Initialization
 8values := [5]int{1, 2, 3, 4, 5}
 9
10// Slices: A subarray that acts as a reference of an array
11// Determining min and max
12values[1:3] // {2, 3, 4}
13
14// Determining only max will use min = 0
15values[:2] // {1, 2, 3}
16
17// Determining only min will use max = last element
18values[3:] // {3, 4}
19
20// Length: number of elements that a slice contains
21len(values) // 5
22
23// Capacity: number of elements that a slice can contain
24values = values[:1]
25len(values) // 2
26cap(values) // 5
27
28// Slice literal
29slice := []bool{true, true, false}
30
31// make function: create a slice with length and capacity
32slice := make([]int, 5, 6) // make(type, len, cap)
33
34// Append new element to slice
35slice := []int{ 1, 2 }
36slice = append(slice, 3)
37slice // { 1, 2, 3 }
38slice = append(slice, 3, 2, 1)
39slice // { 1, 2, 3, 3, 2, 1 }
40
41// For range: iterate over a slice
42slice := string["W", "o", "w"]
43
44for i, value := range slice {
45    i // 0, then 1, then 2
46    value // "W", then "o", then "w"
47}
48
49// Skip index or value
50
51for i := range slice {
52    i // 0, then 1, then 2
53}
54
55for _, value := range slice {
56   value // "W", then "o", then "w"
57}

Return to Summary

Functions

 1// Functions acts as a scoped block of code
 2func sayHello() {
 3    // Hello World!
 4}
 5sayHello() // Hello World!
 6
 7// Functions can take zero or more parameters, as so return zero or more parameters
 8func sum(x int, y int) int {
 9    return x + y
10}
11sum(3, 7) // 10
12
13// Returned values can be named and be used inside the function
14func doubleAndTriple(x int) (double, triple int) {
15    double = x * 2
16    triple = x * 3
17    return
18}
19d, t := doubleAndTriple(5)
20// d = 10
21// t = 15
22
23// Skipping one of the returned values
24_, t := doubleAndTriple(3)
25// t = 9
26
27// Functions can defer commands. Defered commands are
28// runned in a stack order after the execution and
29// returning of a function
30var aux = 0
31
32func switchValuesAndDouble(x, y int) {
33    aux = x
34    defer aux = 0 // cleaning variable to post use
35    x = y * 2
36    y = aux * 2
37}
38
39a, b = 2, 5
40switchValuesAndDouble(2, 5)
41
42// a = 10
43// b = 4
44// aux = 0
45
46// Functions can be handled as values and be anonymous functions
47func calc(fn func(int, int) int) int {
48    return fn(2, 6)
49}
50
51func sum(x, y int) int {
52    return x + y
53}
54
55func mult(x, y int) int {
56    return x * y
57}
58
59calc(sum) // 8
60calc(mult) // 12
61calc(
62    func(x, y int) int {
63		return x / y
64    }
65) // 3
66
67// Function closures: a function that returns a function
68// that remembers the original context
69func calc() func(int) int {
70    value := 0
71    return func(x int) int {
72        value += x
73        return value
74    }
75}
76
77calculator := calc()
78calculator(3) // 3
79calculator(45) // 48
80calculator(12) // 60

Return to Summary

Structs

Structs are a way to arrange data in specific formats.

 1// Declaring a struct
 2type Person struct {
 3    Name string
 4    Age int
 5}
 6
 7// Initializing
 8person := Person{"John", 34}
 9person.Name // "John"
10person.Age // 34
11
12person2 := Person{Age: 20}
13person2.Name // ""
14person2.Age // 20
15
16person3 := Person{}
17person3.Name // ""
18person3.Age // 0

Return to Summary

Maps

Maps are data structures that holds values assigneds to a key.

 1// Declaring a map
 2var cities map[string]string
 3
 4// Initializing
 5cities = make(map[string]string)
 6cities // nil
 7
 8// Insert
 9cities["NY"] = "EUA"
10
11// Retrieve
12newYork = cities["NY"]
13newYork // "EUA"
14
15// Delete
16delete(cities, "NY")
17
18// Check if a key is setted
19value, ok := cities["NY"]
20ok // false
21value // ""

Return to Summary

Pointers

Pointers are a direct reference to a memory address that some variable or value is being stored.

 1// Pointers has *T type
 2var value int
 3var pointer *int
 4
 5// Point to a variable memory address with &
 6value = 3
 7pointer = &value
 8
 9pointer // 3
10pointer = 20
11pointer // 20
12pointer += 5
13pointer // 25
14
15// Pointers to structs can access the attributes
16type Struct struct {
17    X int
18}
19
20s := Struct{3}
21pointer := &s
22
23s.X // 3

Obs: Unlike C, Go doesn’t have pointer arithmetics.

Return to Summary

Methods and Interfaces

Go doesn’t have classes. But you can implement methods, interfaces and almost everything contained in OOP, but in what gophers call “Go Way”

 1type Dog struct {
 2    Name string
 3}
 4
 5func (dog *Dog) bark() string {
 6    return dog.Name + " is barking!"
 7}
 8
 9dog := Dog{"Rex"}
10dog.bark() // Rex is barking!

Interfaces are implicitly implemented. You don’t need to inform that your struct are correctly implementing a interface if it already has all methods with the same name of the interface. All structs implement the interface{} interface. This empty interface means the same as any.

 1// Car implements Vehicle interface
 2type Vehicle interface {
 3    Accelerate()
 4}
 5
 6type Car struct {
 7
 8}
 9
10func (car *Car) Accelerate() {
11    return "Car is moving on ground"
12}

Return to Summary

Errors

Go doesn’t support throw, try, catch and other common error handling structures. Here, we use error package to build possible errors as a returning parameter in functions

 1import "errors"
 2
 3// Function that contain a logic that can cause a possible exception flow 
 4func firstLetter(text string) (string, error) {
 5    if len(text) < 1 {
 6        return nil, errors.New("Parameter text is empty")
 7    }
 8    return string(text[0]), nil
 9}
10
11a, errorA := firstLetter("Wow")
12a // "W"
13errorA // nil
14
15b, errorB := firstLetter("")
16b // nil
17errorB // Error("Parameter text is empty")

Return to Summary

Testing

Go has a built-in library to unit testing. In a separate file you insert tests for functionalities of a file and run go test package to run all tests of the actual package or go test path to run a specific test file.

 1// main.go
 2func Sum(x, y int) int {
 3    return x + y
 4}
 5
 6// main_test.go
 7import ( 
 8    "testing"
 9    "reflect"
10)
11
12func TestSum(t *testing.T) {
13    x, y := 2, 4
14    expected := 2 + 4
15
16    if !reflect.DeepEqual(sum(x, y), expected) {
17        t.Fatalf("Function Sum not working as expected")
18    }
19}

Return to Summary

Concurrency

One of the main parts that make Go attractive is its form to handle with concurrency. Different than parallelism, where tasks can be separated in many cores that the machine processor have, in concurrency we have routines that are more lightweight than threads and can run asynchronously, with memory sharing and in a single core.

  1// Consider a common function, but that function can delay itself because some processing
  2func show(from string) {
  3	for i := 0; i < 3; i++ {
  4		fmt.Printf("%s : %d\n", from, i)
  5	}
  6}
  7
  8// In a blocking way...
  9func main() {
 10	show("blocking1")
 11	show("blocking2")
 12
 13	fmt.Println("done")
 14}
 15/*  blocking1: 0
 16    blocking1: 1
 17    blocking1: 2
 18    blocking2: 0
 19    blocking2: 1
 20    blocking2: 2
 21    done 
 22*/
 23
 24// Go routines are a function (either declared previously or anonymous) called with the keyword go
 25func main() {
 26	go show("routine1")
 27	go show("routine2")
 28
 29	go func() {
 30		fmt.Println("going")
 31	}()
 32
 33	time.Sleep(time.Second)
 34
 35	fmt.Println("done")
 36}
 37
 38/*  Obs: The result will depends of what processes first
 39    routine2: 0
 40    routine2: 1
 41    routine2: 2
 42    going
 43    routine1: 0
 44    routine1: 1
 45    routine1: 2
 46    done
 47*/
 48
 49// Routines can share data with channels
 50// Channels are queues that store data between multiple routines
 51msgs := make(chan string)
 52
 53go func(channel chan string) {
 54    channel <- "ping"
 55}(msgs)
 56
 57go func(channel chan string) {
 58    channel <- "pong"
 59}(msgs)
 60
 61fmt.Println(<-msgs) // pong
 62fmt.Println(<-msgs) // ping
 63
 64// Channels can be bufferized. Buffered channels will accept a limited number of values and when someone try to put belong their limit, it will throw and error
 65numbers := make(chan int, 2)
 66
 67msgs<-0
 68msgs<-1
 69msgs<-2
 70
 71// fatal error: all goroutines are asleep - deadlock!
 72
 73// Channels can be passed as parameter where the routine can only send or receive
 74numbers := make(chan int)
 75
 76go func(sender chan<- int) {
 77    sender <- 10
 78}(numbers)
 79
 80go func(receiver <-chan int) {
 81    fmt.Println(<-receiver) // 10
 82}(numbers)
 83
 84time.Sleep(time.Second)
 85
 86// When working with multiple channels, the select can provide a control to execute code accordingly of what channel has bring a message
 87c1 := make(chan string)
 88c2 := make(chan string)
 89
 90select {
 91case msg1 := <-c1:
 92    fmt.Println("received", msg1)
 93case msg2 := <-c2:
 94    fmt.Println("received", msg2)
 95default:
 96    fmt.Println("no messages")
 97}
 98
 99go func() {
100    time.Sleep(1 * time.Second)
101    c1 <- "channel1 : one"
102}()
103go func() {
104    time.Sleep(2 * time.Second)
105    c2 <- "channel2 : one"
106}()
107
108for i := 0; i < 2; i++ {
109    select {
110    case msg1 := <-c1:
111        fmt.Println("received", msg1)
112    case msg2 := <-c2:
113        fmt.Println("received", msg2)
114    }
115}
116
117/*
118    no messages
119    received channel1: one
120    received channel2: one
121*/
122
123// Channels can be closed and iterated
124channel := make(chan int, 5)
125
126for i := 0; i < 5; i++ {
127    channel <- i
128}
129
130close(channel)
131
132for value := range channel {
133    fmt.Println(value)
134}
135
136/*
137    0
138    1
139    2
140    3
141    4
142*/

Return to Summary

Package fmt

1import "fmt"
2
3fmt.Print("Hello World") // Print in console
4fmt.Println("Hello World") // Print and add a new line in end
5fmt.Printf("%s is %d years old", "John", 32) // Print with formatting
6fmt.Errorf("User %d not found", 123) // Print a formatted error

Return to Summary


Cheat Sheet for Javascript&Node.js&Vue.js
Cheat Sheet for C