Go logoGo INTERMEDIATE

Go

Go (Golang) cheat sheet covering syntax, goroutines, channels, interfaces, error handling, and concurrency patterns with examples.

8 min read
gogolangbackendconcurrentsystemsapimicroservices

Setup & Basics

Getting started with Go

Installation & Setup

Installing Go and setting up development environment

bash
🚀 Compiled language with fast execution
📦 Built-in dependency management with go mod
🔧 Simple toolchain with go command
⚡ Static binaries for easy deployment

Basic Syntax

Go program structure and syntax

go
📝 Static typing with type inference
🎯 Simple, clean syntax without semicolons
🔧 := for short variable declarations
📦 Package-based organization

Data Types & Structures

Go data types, arrays, slices, maps, and structs

Arrays & Slices

Working with arrays and slices

go
📊 Arrays have fixed size, slices are dynamic
🔄 append() to add elements to slices
📦 make() to create slices with capacity
⚡ Slices are references to underlying arrays

Maps

Working with maps (hash tables)

go
🗺️ Hash tables with O(1) average access
🔑 Any comparable type can be a key
❌ Use delete() to remove entries
⚠️ Maps are not thread-safe by default

Structs

Defining and using structs

go
📦 Group related data with structs
🏷️ Tags for JSON/DB field mapping
🔄 Methods with value or pointer receivers
🎯 Composition over inheritance with embedding

Struct Embedding

Composition via embedding structs and interfaces

go
🎯 Go uses composition over inheritance via embedding
💡 Embedded fields and methods are promoted to outer struct
📌 Access via p.City or p.Address.City — both work
⚡ Interfaces can embed other interfaces for composition

Pointers

Working with pointers and memory addresses

Pointers

Pointer basics, dereferencing, and nil pointers

go
🎯 Use & to get address, * to dereference
📌 Go has no pointer arithmetic (safer than C)
💡 Struct fields accessed directly through pointer (no -> needed)
⚡ new() allocates zeroed memory and returns a pointer

Control Flow

Conditionals, loops, and control structures

Conditionals

If statements and switch cases

go
🎯 No parentheses needed around conditions
🔄 Switch doesn't need break (no fallthrough by default)
📦 Type switches for interface type assertion
⚡ Switch can be used without an expression

Loops

For loops and iterations

go
🔄 Only for loops (no while/do-while)
📊 range for iterating collections
🏷️ Labels for breaking nested loops
⚡ range on channels until closed

Functions

Functions, methods, and closures

Functions

Function declaration and usage

go
📦 Multiple return values for errors
🔄 defer for cleanup (LIFO order)
📝 Variadic functions with ...
⚡ Functions are first-class values

Methods

Methods on types and interfaces

go
📦 Methods attached to types with receivers
🔄 Value receivers can't modify, pointer receivers can
🎯 Go auto-dereferences and takes addresses
⚡ Methods can be on any type, not just structs

Closures

Anonymous functions and closures

go
🔄 Closures capture variables by reference, not by value
💡 Common for goroutines, callbacks, and factory functions
📌 Go 1.22+ fixed the loop variable capture bug
⚡ Functions are first-class values in Go

Interfaces

Interface types and polymorphism

Interfaces

Defining and implementing interfaces

go
🎯 Implicit interface implementation
📦 interface{} for any type
🔄 Type assertions and type switches
⚡ Small interfaces are better (Interface Segregation)

Type Assertions & Switches

Extract concrete types from interfaces

go
📌 Always use the comma-ok form to avoid panics
💡 Type switches use .(type) — only works in switch statements
🎯 any is an alias for interface{} since Go 1.18
⚡ Type assertions work on interfaces, not concrete types

Generics

Type parameters and constraints

Generics

Generic functions and types with type parameters

go
🎯 Available since Go 1.18 — use any for unconstrained types
💡 ~ means underlying type (e.g., ~int matches type MyInt int)
📌 comparable constraint allows == and != operations
⚡ Type inference often lets you omit type arguments at call site

Concurrency

Goroutines, channels, and synchronization

Goroutines

Concurrent execution with goroutines

go
🚀 Lightweight threads managed by Go runtime
⚡ Can run millions of goroutines
🔄 Use sync.WaitGroup for synchronization
⚠️ Beware of race conditions - use channels or mutexes

Channels

Communication between goroutines

go
📡 Channels for goroutine communication
🔄 Buffered vs unbuffered channels
🎯 select for multiplexing channel operations
⏱️ Timeouts with time.After()

Select Statement

Multiplex channel operations with select

go
🎯 select blocks until one case is ready (random if multiple)
⏱️ Use time.After for timeout patterns
💡 default case makes select non-blocking
📌 Common for fan-in, timeouts, and cancellation

Sync Primitives

Mutex, WaitGroup, and Once for synchronization

go
📌 Always defer wg.Done() and mu.Unlock() to prevent deadlocks
💡 Use RWMutex when reads vastly outnumber writes
🎯 sync.Once is perfect for lazy initialization
⚡ Prefer channels for communication, mutexes for state protection

Error Handling

Error handling patterns and best practices

Error Handling

Working with errors in Go

go
❌ Errors are values, not exceptions
🔄 Always check returned errors
📦 Wrap errors with context using %w
🎯 errors.Is() and errors.As() for error checking

Defer, Panic & Recover

Deferred execution, panics, and recovery

go
📌 defer runs in LIFO order when the function returns
🎯 Always defer Close(), Unlock(), Done() right after acquiring
⚠️ Only recover from panics at package boundaries — don't use as try/catch
💡 Deferred functions can modify named return values

String Formatting

fmt package verbs and string operations

fmt Verbs & Formatting

Printf verbs and string formatting functions

go
🎯 %v is the go-to verb — works with any type
💡 %+v shows struct field names — great for debugging
📌 Sprintf returns a string, Printf writes to stdout
⚡ Implement String() method to customize %v output

Context

Cancellation, timeouts, and request-scoped values

Context

Cancellation, timeouts, and passing request-scoped data

go
📌 Always pass context as the first function parameter
🎯 Always defer cancel() to prevent context leaks
💡 Use WithValue sparingly — prefer explicit parameters
⚡ context.TODO() for placeholder when unsure which context to use

JSON

Encoding and decoding JSON data

JSON Encoding & Decoding

Marshal, Unmarshal, and struct tags for JSON

go
📌 Use struct tags to control JSON field names and behavior
💡 omitempty skips zero-value fields, "-" excludes entirely
⚡ Use map[string]any for dynamic/unknown JSON structures
🎯 NewEncoder/NewDecoder for streaming — more efficient than Marshal/Unmarshal

HTTP Server & Client

Building HTTP servers and making requests

HTTP Server & Client

net/http server handlers and HTTP client requests

go
🎯 Go 1.22+ ServeMux supports method + path patterns natively
📌 Always defer resp.Body.Close() on HTTP responses
💡 Set server timeouts to prevent slow-client attacks
⚡ Use http.Client with timeout — default has no timeout

Testing

Writing and running tests

Testing

Unit tests and benchmarks

go
🧪 Built-in testing with testing package
📊 Table-driven tests for multiple cases
⚡ Benchmarks with go test -bench
📈 Coverage with go test -cover

Packages & Modules

Package management and module system

Packages & Imports

Organizing code with packages

go
📦 Packages for code organization
🔒 Capitalized names are exported
📁 internal/ for private packages
⚡ go.mod for dependency management