Skip to the content.

Go Cheatsheet

Go (Golang) Cheatsheet

A quick-reference guide for essential and advanced Go concepts, covering types, slices, maps, pointers, interfaces, concurrency primitives, and the Go toolchain.

Variables & Constants

package main

import "fmt"

func main() {
    // 1. Variable Declarations
    var x int = 10              // Explicit type
    var y = "hello"             // Inferred type
    z := true                   // Short declaration operator (inside functions only)

    // Multiple assignments
    a, b := 1, 2

    // 2. Constants
    const Pi = 3.14159          // Compile-time resolved constant
    const (
        StatusOk = 200
        StatusFail = 500
    )
}

Control Flow

// 1. Conditionals (no parentheses, braces required)
if x > 10 {
    fmt.Println("Greater")
} else {
    fmt.Println("Less/Equal")
}

// Inline statement evaluation (scope is restricted to the if/else block)
if val := calculate(); val > 0 {
    fmt.Println(val)
}

// 2. For Loops (Go's only loop structure!)
for i := 0; i < 5; i++ {        // Standard loop
    fmt.Println(i)
}

for x < 100 {                   // While-style loop
    x += 10
}

for {                           // Infinite loop
    break
}

// 3. Switch Statement (No implicit fallthrough, break is automatic)
switch x {
case 1, 2:
    fmt.Println("One or Two")
case 10:
    fmt.Println("Ten")
default:
    fmt.Println("Default")
}

Slices & Maps

// 1. Slices (Dynamically sized arrays)
var s []int                     // nil slice
s = append(s, 1, 2)             // Add elements dynamically

s2 := make([]int, 5, 10)        // Slice with length 5 and capacity 10
s3 := []string{"a", "b", "c"}   // Slice literal

// Slicing operations
subset := s3[1:3]               // ["b", "c"] (index 1 to 2)

// Iterating with Range
for index, value := range s3 {
    fmt.Printf("%d: %s\n", index, value)
}

// 2. Maps (Hash tables)
ages := make(map[string]int)    // Create map
ages["Alice"] = 30

// Map literal
userRoles := map[string]string{
    "admin": "read,write",
    "user":  "read",
}

// Check if key exists (comma ok idiom)
role, ok := userRoles["guest"]  // ok is false if key is missing

// Delete key
delete(userRoles, "user")

Functions, Pointers & defer

// Multiple return values and named returns
func divide(a, b float64) (result float64, err error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    result = a / b
    return result, nil          // Naked return of named variables
}

// Pointers (* = value at pointer, & = address of value)
func updateValue(ptr *int) {
    *ptr = 20                   // Dereference and assign new value
}

// defer (Delays execution of function until parent function returns - useful for resource cleanup)
func readFile() {
    file, _ := os.Open("data.txt")
    defer file.Close()          // Closed automatically at end of function
    // ... read file ...
}

Structs & Methods

type User struct {
    ID    int
    Name  string
    Email string
}

// Value Receiver Method (Operates on copy of struct)
func (u User) Greet() string {
    return "Hello, " + u.Name
}

// Pointer Receiver Method (Operates on original struct, can modify fields)
func (u *User) UpdateEmail(newEmail string) {
    u.Email = newEmail
}

// Instantiate struct
u := User{ID: 1, Name: "Alice", Email: "a@b.com"}
u.UpdateEmail("new@b.com")      // Syntax shorthand for (&u).UpdateEmail(...)

Interfaces

// Defining an Interface
type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct {
    Radius float64
}

// Implementing an Interface (Go interfaces are implemented implicitly!)
func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * 3.14 * c.Radius
}

// Empty Interface (Any type implements the empty interface)
var anyValue interface{} = "hello"

Concurrency (Goroutines & Channels)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        results <- j * 2        // Send result to channel
    }
}

func main() {
    // 1. Goroutine (Lightweight thread managed by Go runtime)
    go fmt.Println("Hello from background")

    // 2. Channels (Thread-safe message pipes)
    ch := make(chan string)
    go func() { ch <- "ping" }() // Send to channel
    msg := <-ch                  // Receive from channel

    // 3. Buffered Channels
    bufCh := make(chan int, 2)  // Buffer size 2 (does not block sender until full)

    // 4. select (Blocks until one of its channel cases can execute)
    select {
    case msg1 := <-ch:
        fmt.Println("Received", msg1)
    case bufCh <- 10:
        fmt.Println("Sent to buffer")
    default:
        fmt.Println("No channel active")
    }
}

Concurrency Sync Primitives

import "sync"

// 1. WaitGroup (Block execution thread until multiple goroutines finish)
var wg sync.WaitGroup

for i := 1; i <= 3; i++ {
    wg.Add(1)                   // Increment WaitGroup counter
    go func(id int) {
        defer wg.Done()         // Decrement counter when finished
        fmt.Println("Job", id)
    }(i)
}
wg.Wait()                       // Block until counter reaches 0

// 2. Mutex (Ensure only one goroutine accesses critical section at a time)
var (
    mu    sync.Mutex
    count = 0
)

func increment() {
    mu.Lock()
    defer mu.Unlock()
    count++
}

Error Handling

import "errors"

// 1. Returning Errors
func findUser(id int) (*User, error) {
    if id <= 0 {
        return nil, errors.New("invalid user ID") // Standard error creation
    }
    return &User{ID: id}, nil
}

// 2. Custom Error Structures
type QueryError struct {
    Query string
    Err   error
}

func (e *QueryError) Error() string {
    return fmt.Sprintf("Query %q failed: %v", e.Query, e.Err)
}

Go CLI Toolchain

go mod init <module_name>     # Initialize a new Go module (generates go.mod)
go run main.go                # Compile and run the specified Go file immediately
go build                      # Compile active directory package into executable binary
go build -o app_bin           # Compile and output binary using a custom filename
go test                       # Run all unit tests (*_test.go) in the active folder
go test -v                    # Run tests in verbose mode (list individual run outcomes)
go get <package_path>         # Download and add a remote dependency to go.mod
go fmt                        # Automatically format all Go files in active package
go vet                        # Run static analysis tool to find common semantic bugs