Cheatsheet - Go

Tooling & CLI Commands

# Modules & dependencies
go mod init <module-path>    # Initialize new module
go mod tidy                  # Add missing and remove unused modules
go mod download              # Download modules to local cache
go list -m all               # List current module and dependencies

# Build & execution
go run main.go               # Compile and run in temporary directory
go build -o app main.go      # Compile binary
go install                   # Compile and install to $GOBIN ($GOPATH/bin)
go clean -cache              # Clear build cache

# Testing & quality
go test -v ./...             # Run all tests in module
go test -race ./...          # Run tests with race detector
go test -bench=. ./...       # Run benchmarks
go vet ./...                 # Report suspicious constructs
gofmt -s -w .                # Format source files

Variables, Types & Declarations

// Variable declarations
var a int = 10               // Explicit type
var b = "hello"              // Inferred type
c := 3.14                    // Short declaration (inside functions only)
var p *int = &a              // Pointer (* to dereference, & for address)

// Constants & iota enum
const Pi = 3.14159
const (
    StatusPending = iota    // 0
    StatusActive            // 1
    StatusFailed            // 2
)

// Conversions
f := float64(a)
s := string([]byte{'h', 'i'})

Slices & Arrays

// Arrays (fixed size, value type)
arr := [3]int{1, 2, 3}

// Slices (dynamic view into underlying array: pointer, length, capacity)
s := []int{1, 2, 3}
s = make([]int, 0, 10)       // len = 0, cap = 10

// Append & expansion
s = append(s, 4, 5)
s = append(s, arr[:]...)     // Unpack and append slice

// Slicing: [low:high] (len = high-low)
sub := s[1:3]
len(s)                       // Number of elements
cap(s)                       // Elements before reallocating underlying array

// Delete element at index i (preserves order)
s = append(s, 10, 20, 30, 40)
i := 1
s = append(s[:i], s[i+1:]...) // [10, 30, 40]

// Copy
dest := make([]int, len(s))
copy(dest, s)                // Returns number of copied elements

Maps

// Initialization
m := make(map[string]int)
m["apple"] = 5

// Literal initialization
scores := map[string]int{
    "alice": 95,
    "bob":   88,
}

// Lookup (comma-ok idiom)
val, ok := scores["alice"]
if ok {
    fmt.Println("Found:", val)
}

// Delete key (noop if key absent)
delete(scores, "bob")

// Map length
count := len(scores)

Control Flow

// if with initialization statement
if val, ok := m["apple"]; ok && val > 0 {
    fmt.Println(val)
} else {
    fmt.Println("Not found or zero")
}

// For loop variations (Go has no 'while' keyword)
for i := 0; i < 5; i++ { }    // Standard C-style
for a < b { }                // While-style condition
for { break }                // Infinite loop

// Range over slice / map / string
for idx, val := range s { }
for key, val := range m { }
for key := range m { }       // Keys only
for _, r := range "hello" { } // Runes and byte offsets

// Switch statement (no automatic fallthrough)
switch val {
case 1, 2:
    fmt.Println("one or two")
case 3:
    fmt.Println("three")
default:
    fmt.Println("other")
}

Structs, Methods & Interfaces

type User struct {
    ID   int
    Name string
}

// Value receiver (operates on a copy)
func (u User) Greeting() string {
    return "Hi, " + u.Name
}

// Pointer receiver (mutates original struct, avoids copying large structs)
func (u *User) SetName(name string) {
    u.Name = name
}

// Interface (implemented implicitly by any matching type)
type Greeter interface {
    Greeting() string
}

// Type assertion & type switch
var g Greeter = User{ID: 1, Name: "Sam"}
if u, ok := g.(User); ok {
    fmt.Println("User ID:", u.ID)
}

switch v := g.(type) {
case User:
    fmt.Println("Concrete User:", v.Name)
default:
    fmt.Println("Unknown type")
}

Error Handling

import (
    "errors"
    "fmt"
)

var ErrNotFound = errors.New("item not found")

func find(id int) (string, error) {
    if id <= 0 {
        // Wrap error with %w to allow unwrap / inspection
        return "", fmt.Errorf("lookup id %d: %w", id, ErrNotFound)
    }
    return "ok", nil
}

// Inspect error chains
res, err := find(0)
if err != nil {
    if errors.Is(err, ErrNotFound) {
        fmt.Println("Item was missing")
    }
}

Concurrency: Goroutines & Channels

// Launch goroutine
go func(msg string) {
    fmt.Println(msg)
}("hello")

// Channels (unbuffered blocks sender until receiver is ready)
ch := make(chan int)
go func() {
    ch <- 42                 // Send
}()
val := <-ch                  // Receive

// Buffered channel
bufCh := make(chan string, 2)
bufCh <- "a"
bufCh <- "b"
close(bufCh)                 // Close channel

// Drain closed channel (ok is false when empty and closed)
for v := range bufCh {
    fmt.Println(v)
}

// Select statement (multiplex channel operations)
select {
case msg := <-ch:
    fmt.Println("Received:", msg)
case bufCh <- "data":
    fmt.Println("Sent")
default:
    fmt.Println("Non-blocking fallback")
}

// WaitGroup for coordinating multiple goroutines
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        // work...
    }(i)
}
wg.Wait()

HTTP Server & Client (net/http)

import (
    "io"
    "net/http"
    "time"
)

// HTTP Handlers
func rootHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.WriteHeader(http.StatusOK)
    io.WriteString(w, "Hello, World!\n")
}

// Server setup
mux := http.NewServeMux()
mux.HandleFunc("/", rootHandler)
mux.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    io.WriteString(w, `{"status":"ok"}`)
})

server := &http.Server{
    Addr:         ":8080",
    Handler:      mux,
    ReadTimeout:  5 * time.Second,
    WriteTimeout: 10 * time.Second,
}
// server.ListenAndServe()

// Client GET request
resp, err := http.Get("https://api.example.com/data")
if err == nil {
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    _ = body
}

Templates (text/template & html/template)

html/template provides the exact same API as text/template, but automatically context-escapes HTML, JS, CSS, and URLs against XSS.

import (
    "html/template"
    "os"
    "strings"
)

// Pipeline actions syntax:
// {{ .FieldName }}                   Field or map key lookup
// {{ . | len }}                      Function pipeline
// {{ if .Active }} ... {{ end }}     Conditionals (eq, ne, lt, gt, and, or, not)
// {{ range $k, $v := .Map }} ... {{ else }} No items {{ end }}
// {{- /* trim left */ -}}            Whitespace trimming

funcMap := template.FuncMap{
    "upper": strings.ToUpper,
}

tmpl := template.Must(template.New("demo").Funcs(funcMap).Parse(`
Hello, {{ .Name | upper }}!
{{ range .Items -}}
- {{ . }}
{{ else -}}
No items.
{{ end -}}
`))

data := struct {
    Name  string
    Items []string
}{Name: "World", Items: []string{"Alpha", "Beta"}}

tmpl.Execute(os.Stdout, data)

JSON Serialization (encoding/json)

import "encoding/json"

type Config struct {
    Host     string `json:"host"`
    Port     int    `json:"port"`
    Secret   string `json:"-"`                // Excluded from JSON
    Optional string `json:"optional,omitempty"` // Omitted if zero-value
}

// Marshal to JSON bytes
cfg := Config{Host: "localhost", Port: 8080}
data, err := json.Marshal(cfg)
pretty, err := json.MarshalIndent(cfg, "", "  ")

// Unmarshal from JSON bytes
var parsed Config
if err := json.Unmarshal(data, &parsed); err != nil {
    log.Fatal(err)
}

Common String Functions (strings)

import "strings"

strings.Contains("golang", "lang")      // true
strings.HasPrefix("v1.2.0", "v")        // true
strings.HasSuffix("archive.zip", ".zip") // true
strings.Split("a,b,c", ",")             // []string{"a", "b", "c"}
strings.Join([]string{"a", "b"}, "-")   // "a-b"
strings.ReplaceAll("foo bar foo", "foo", "qux") // "qux bar qux"
strings.TrimSpace("  trimmed  \n")      // "trimmed"
strings.ToLower("GO")                   // "go"