Golang Cheatsheet Zero To Mastery V1.01
Golang Cheatsheet Zero To Mastery V1.01
CHEAT SHEET
JAYSON LENNON
V1.01
HEEELLLOOOOO!
I’m Andrei Neagoie, Founder and Lead Instructor of the Zero To Mastery Academy.
After working as a Senior Software Developer over the years, I now dedicate 100% of my time to
teaching others valuable software development skills, help them break into the tech industry, and
advance their careers.
In only a few years, over 600,000 students around the world have taken Zero To Mastery courses
and many of them are now working at top tier companies like Apple, Google, Amazon, Tesla, IBM,
Facebook, and Shopify, just to name a few.
This cheat sheet, created by our Golang instructor (Jayson Lennon) provides you with the key
Golang concepts that you need to know and remember.
If you want to not only learn Golang but also get the exact steps to build your own projects and get
hired as a DevOps Engineer or Fullstack Developer, then check out our Career Paths.
Happy Coding!
Andrei
P.S. I also recently wrote a book called Principles For Programmers. You can download the first
five chapters for free here.
Golang Cheat Sheet
Table of Contents
Operators
Mathematical, Bitwise, Comparison, Logical, Other
Data Types
Data Types, Signed Integers, Unsigned Integers, Floating Point Numbers
Declarations
Variables, Type Aliases, Constants, iota Enumeration Pattern
Functions
Functions, Function Literals / Closures, Variadics
fmt
fmt
Escape Sequences
Escape Sequences
Control Structures
If, Switch, Loops
Arrays
Arrays, Slices
Maps
Maps
Pointers
Pointers
Receiver Functions
Receiver Functions
Interfaces
Interfaces
Type Embedding
Type Embedding, Interfaces, Structs
Concurrency
Concurrency, Defer, Goroutines, WaitGroups, Mutex, Channels
Errors
Errors
Testing
Testing
CLI
CLI
Modules
Modules
Packages
Packages
Bitwise
Operator Description
& bitwise and
\| bitwise or
^ bitwise xor
Comparison
Operator Description
== equal
!= not equal
Logical
Operator Description
&& and
\|\| or
! not
Other
Operator Description
<< left shift
>> right shift
Data Types
Raw strings and raw runes will be displayed as-is (no escape sequences).
Create with "" (double quotes) or `` (backticks) for raw string; contains any
string ""
number of Unicode code points
Create with '' (single quotes) or `` (backticks) for raw rune; contains a single
rune 0
Unicode code point
Signed Integers
Type Default Range
int8 0 -128..127
int16 0 -32768..32767
int 0 -2147483648..2147483647
int32 0 -2147483648..2147483647
rune 0 -2147483648..2147483647
int64 0 -9223372036854775808..9223372036854775807
Unsigned Integers
Type Default Range
uint16 0 0.65535
uint64 0 0..18446744073709551615
Declarations
Variables
Naming convention is camelCase . Variable names can only be declared once per scope
(function body, package, etc.).
var d, e, f = 1, 2, "f" // create 3 variables at once. types inferred (int, int, string)
Shorthand notation creates and then assigns in a single statement. Shorthand can only
be used within function bodies:
"Comma, ok" idiom allows re-use of last variable in compound create & assign:
Type Aliases
Type aliases can help clarify intent. They exist as names only, and are equivalent to the
aliased type.
Constants
Naming convention is PascalCase . Constant names can only be declared once per scope
(function body, package, etc.).
// block declaration
const (
A = 0
B = 1
C = 2
)
// iota
const (
A = iota // 0
B // 1
C // 2
_ // 3 (skipped)
E // 4
)
Functions
All function calls in Go are pass-by-value, meaning a copy of the argument is made for
every function call.
Function Literals
sample := 5
// closure
test := func() {
// capture `sample` variable
fmt.Println(sample)
}
test() // output: 5
Variadics
Variadics allow a function to accept any number of parameters.
a := []int{1, 2, 3}
b := []int{4, 5, 6}
// same as above
answer = sum(1, 2, 3, 4, 5, 6) // many arguments
fmt
The fmt package is used to format strings. Verbs set what type of formatting is used for
specific data types. See the docs for a full list of verbs.
Verb Description
%v default
%+v for structs: field names & values; default otherwise
%#v for structs: type name, field names, values; default otherwise
writer := bytes.NewBufferString("")
fmt.Fprintf(writer, "printf into a Writer")
fmt.Fprint(writer, "print into a Writer")
fmt.Fprintln(writer, "println into a Writer")
Escape Sequences
Escape sequences allow input of special or reserved characters within a string or rune.
Sequence Result
\\\\ backslash: \\
\\n newline
\\t horizontal tab
Control Structures
If
if condition {
// execute when true
} else {
// execute when false
}
if condition == 1 {
// ...
} else if condition == 2 {
// ...
} else {
// ...
}
Switch
switchcan be used in place of long if..else chains. Cases are evaluated from top to
bottom and always stop executing once a case is matched (unless the fallthrough
keyword is provided).
Loops
// C-style loop
// create variable i and as long as i < 10, increment i by 1 each iteration
for i := 0; i < 10; i++ {
}
// while loop
i := 0
for i < 10 {
i++
}
// infinite loop
for {
if somethingHappened {
// exit loop
break
} else if nothingHappened {
// jump straight to next iteration
continue
}
}
Slices
// 4 element array
nums := [...]int{1, 2, 3, 4}
// 0 1 2 3 <- index
// make a slice
s1 := nums[:] // [1, 2, 3, 4] all
s2 := nums[1:] // [2, 3, 4] index 1 until end
s3 := s2[1:] // [3, 4] index 1 until end
s4 := nums[:2] // [1, 2] start until index 2 (exclusive)
// multidimensional slices
board := [][]string{
[]string{"_", "_", "_"},
// type annotation optional
{"_", "_", "_"},
{"_", "_", "_"},
}
board[0][0] = "X"
board[2][2] = "O"
board[1][2] = "X"
board[1][0] = "O"
board[0][2] = "X"
Maps
Maps are key/value pairs. Equivalent to Dictionary, HashMap, and Object types from
other languages.
// ignore values
for key, _ := range myMap {
// ...
}
// ignore keys
for _, value := range myMap {
// ...
}
Structures
Structures are made of fields, which contain some data. Similar to a Class in other
languages.
// instantiation
data := Sample{"data", 1, 2} // all fields required when not using names
data := Sample{} // all default values
Anonymous Structures
Pointers
Pointers are memory addresses stored in variables. They point to other variables, and
can be dereferenced to access the data at the address they point to.
//
// 5 | value
Receiver Functions
Receiver functions allow functionality to be tied to structures. Use either all pointer
receivers or all value receivers on a single structure to avoid compilation errors.
// regular function
func shiftBy(x, y int, coord *Coordinate) {
coord.X += x
coord.Y += y
}
// receiver function
// use pointer to modify structure
func (coord *Coordinate) shiftBy(x, y int) {
coord.X += x
coord.Y += y
}
coord := Coordinate{5, 5}
shiftBy(1, 1, &coord) // coord{6, 6}
coord.shiftBy(1, 1) // coord{7, 7}
// receiver function
// original structure unmodified
func (coord Coordinate) shiftByValue(x, y int) Coordinate {
coord.X += x
Interfaces
Interfaces allow functionality to be specified for arbitrary data types.
// declare an interface
type MyInterface interface {
MyFunc()
}
execute(&s) // OK
f := FooType(1)
b := BarType(2)
run(&f) // prints "foo"
run(&b) // prints "bar"
Type Embedding
Type embedding allows types to be "embedded" in another type. Doing this provides all
the fields and functionality of the embedded types at the top level. Similar to inheritance
Interfaces
Embedding an interface within another interface creates a composite interface. This
composite interface requires all embedded interface functions to be implemented.
// embed 2 types
type Talker interface {
Whisperer // only the type name is used for embedding
Yeller
}
Structs
Embedding a struct within another struct creates a composite structure. This composite
structure will have access to all embedded fields and methods at the top level, through
a concept known as method and field promotion.
Concurrency
Go's concurrency model abstracts both threaded and asynchronous operations via the
go keyword.
Defer
deferallows a function to be ran after the current function. It can be utilized for cleanup
operations.
func foo() {
// defer this function call until after foo() completes
defer fmt.Println("done!")
fmt.Println("foo'd")
}
foo()
// output:
// foo'd
// done!
Goroutines
Goroutines are green threads that are managed by Go. They can be both computation
heavy and wait on external signals.
func longRunning() {
time.Sleep(1000 * time.Millisecond)
fmt.Println("longrunning() complete")
}
// output:
// goroutine running
// longrunning() complete
// program end
counter := 0
// create closure
wait := func(ms time.Duration) {
time.Sleep(ms * time.Millisecond)
// capture the counter
counter += 1
}
fmt.Println("Launching goroutines")
// output:
// Launching goroutines
// Launched. Counter = 0
// Launched. Counter = 3
WaitGroups
The main thread of the program will not wait for goroutines to finish. WaitGroup provides
a counter that can be waited upon until it reaches 0. This can be used to ensure that all
work is completed by goroutines before exiting the program.
sum := 0
for i := 0; i < 20; i++ {
wg.Add(1) // add 1 to the WaitGroup counter
value := 1
// spawn a goroutine
go func() {
// defer execution of wg.Done()
defer wg.Done() // wg.Done() decrements the counter by 1
Mutex
Mutex (MUTual EXclusion) provides a lock that can only be accessed by one goroutine
at a time. This is used to synchronize data across multiple goroutines. Attempting to
lock a Mutex will block (wait) until it is safe to do so. Once locked, the protected data
can be operated upon since all other goroutines are forced to wait until the lock is
available. Unlock the Mutex once work is completed, so other goroutines can access it.
func main() {
// Mutex abstracted behind SyncedData
data := SyncedData{inner: make(map[string]int)}
// Can be accessed by any number of goroutines since Mutex
// will wait to become unlocked.
data.Insert("sample a", 5)
data.InsertDeferred("sample b", 10)
}
Channels
Channels provide a communication pipe between goroutines. Data is sent into one end
of the channel, and received at the other end of the channel.
go func() {
// Blocks because channel is full. Since we
// are in a goroutine, main thread can continue
channel <- 3
}()
// infinite loop
for {
// `select` will poll each channel trying to read data.
// There is no ordering like a `switch`; channels are randomly polled.
select {
case o := <-one: // try to read from channel one
fmt.Println("one:", o)
case t := <-two: // try to read from channel two
fmt.Println("two:", t)
// use time.After() to create a timeout (maximum wait time)
case <-time.After(300 * time.Millisecond):
fmt.Println("timed out")
return
// when there is no data to read from any channel, run the default
default:
fmt.Println("no data to receive")
// sleep here so we don't consume all CPU cycles
time.Sleep(50 * time.Millisecond)
}
}
Errors
Go has no exceptions. Errors are returned as interface error values, or the program
can abort completely with a panic.
It is possible to create your own error types that contain relevant data related to the
error.
sample/
sample.go
sample_test.go
sample.go:
package sample
sample_test.go:
package sample
// test table
func TestDoubleTable(t *testing.T) {
// anonymous struct containing input and expected output
table := []struct {
input int
want int
}{
// input/output pairs
{0, 0},
{1, 2},
{2, 4},
CLI
Command Description
go run ./sourceFile.go run source file containing func main()
Modules
Modules are composed of multiple packages. Each Go project has a go.mod file
containing the Go version, module name, and dependencies.
go.mod:
module example.com/practice
go 1.17
Packages
Packages should have a single purpose. All files that are part of a single package are
treated as one large file.
projectRoot/
go.mod
package1/
package1.go
extraStuff.go
package2/
package2.go
// using packages
package main
import "package1"
import (
"package2"
"namespace/packageName"
. "pkg" // glob import; no need to reference `pkg` in code
pk "namespace/mySuperLongPackageName" // rename to `pk`
)
Back To Top