Go (Golang) Cheat Sheet

A comprehensive quick reference for Go (Golang) covering variables, data types, control flow, functions, concurrency primitives, error handling, structs, interfaces, and the most-used standard library packages. Bookmark this page and keep it open while you code.

Table of Contents

Variables & Constants

Pattern Description Example
var declaration Declare with explicit type var name string = "Alice"
var with inference Type inferred from value var age = 30
Short declaration := Declare and assign (inside functions only) count := 42
Multiple variables Declare several at once var x, y, z int = 1, 2, 3
Var block Group variable declarations var (
  name string
  age int
)
const Immutable value (compile-time) const Pi = 3.14159
const block Group constants const (
  StatusOK = 200
  StatusNotFound = 404
)
iota Auto-incrementing constant generator const (
  Red = iota // 0
  Green // 1
  Blue // 2
)
Zero values Default value when not initialized // int: 0, string: "", bool: false, pointer: nil
Type conversion Explicit type casting (no implicit conversion) f := float64(intVal)
package main const ( KB = 1024 MB = KB * 1024 GB = MB * 1024 ) func main() { name := "Go" // short declaration (type inferred as string) var version float64 = 1.22 // explicit type year, month := 2024, "March" // multiple assignment _ = version // blank identifier suppresses "unused" error _ = year _ = month _ = name }
Tip: Use := inside functions for concise declarations. Use var for package-level variables or when you need to declare without initializing.

Data Types

Type Description Zero Value
bool Boolean true/false false
string UTF-8 encoded text (immutable) ""
int, int8, int16, int32, int64 Signed integers (int is platform-dependent: 32 or 64 bit) 0
uint, uint8, uint16, uint32, uint64 Unsigned integers 0
float32, float64 IEEE-754 floating point 0.0
complex64, complex128 Complex numbers (real + imaginary) (0+0i)
byte Alias for uint8 0
rune Alias for int32 (represents a Unicode code point) 0
uintptr Integer large enough to hold a pointer value 0
var ( isReady bool = true name string = "Gopher" age int = 10 price float64 = 19.99 initial rune = 'G' // Unicode code point U+0047 data byte = 0xFF z complex128 = 3 + 4i ) // Type alias type UserID int64 type Celsius float64

Control Flow

Statement Description Example
if / else Conditional branching (no parentheses needed) if x > 10 { ... } else { ... }
if with init Short statement before condition if err := doWork(); err != nil { ... }
for (classic) C-style for loop for i := 0; i < 10; i++ { ... }
for (while) Condition-only loop for x < 100 { x *= 2 }
for (infinite) Loop forever (break to exit) for { ... }
for range Iterate over slices, maps, strings, channels for i, v := range slice { ... }
switch Multi-way branching (no fallthrough by default) switch day { case "Mon": ... }
switch (no expr) Clean replacement for if/else chains switch { case x > 0: ... }
switch type Branch on interface type switch v := i.(type) { case int: ... }
select Wait on multiple channel operations select { case msg := <-ch: ... }
defer Schedule call to run when function returns (LIFO) defer file.Close()
break / continue Exit loop or skip to next iteration if done { break }
goto Jump to label (rarely used) goto cleanup
// if with init statement if f, err := os.Open("file.txt"); err != nil { log.Fatal(err) } else { defer f.Close() // use f } // for range over a map for key, value := range myMap { fmt.Printf("%s: %v\n", key, value) } // switch with no expression switch { case score >= 90: grade = "A" case score >= 80: grade = "B" default: grade = "C" } // select on channels select { case msg := <-ch1: fmt.Println(msg) case ch2 <- "ping": fmt.Println("sent") case <-time.After(5 * time.Second): fmt.Println("timeout") }

Functions

Pattern Description Example
Basic function Simple function with typed params func add(a, b int) int { return a + b }
Multiple returns Return more than one value func divide(a, b float64) (float64, error)
Named returns Name return values, use naked return func calc(x int) (result int, err error)
Variadic function Accept any number of arguments func sum(nums ...int) int
Spread operator Pass slice as variadic args sum(numbers...)
Function value Functions are first-class values fn := func(x int) int { return x * 2 }
Closure Function that captures surrounding variables func counter() func() int { ... }
init() Package initializer (runs before main) func init() { ... }
Function type Define a function signature as a type type Handler func(string) error
// Multiple return values (idiomatic Go error handling) func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("division by zero") } return a / b, nil } // Variadic function func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } // Closure func counter() func() int { count := 0 return func() int { count++ return count } } next := counter() fmt.Println(next()) // 1 fmt.Println(next()) // 2

Arrays & Slices

Operation Description Example
Array (fixed size) Fixed-length, value type var a [5]int
Array literal Initialize with values a := [3]string{"a", "b", "c"}
Array with ... Let compiler count elements a := [...]int{1, 2, 3, 4}
Slice (dynamic) Dynamic-length reference to underlying array s := []int{1, 2, 3}
make() Create slice with length and capacity s := make([]int, 5, 10)
append() Add elements (may reallocate) s = append(s, 4, 5, 6)
Append slice Append one slice to another s = append(s, other...)
len() / cap() Length and capacity of slice fmt.Println(len(s), cap(s))
Slice expression Create sub-slice [low:high] sub := s[1:4]
Full slice expr Control capacity [low:high:max] sub := s[1:4:5]
copy() Copy elements between slices n := copy(dst, src)
Delete element Remove element at index i s = append(s[:i], s[i+1:]...)
Nil slice Uninitialized slice (length 0, nil) var s []int // s == nil
// Slices in action nums := []int{10, 20, 30, 40, 50} // Slicing: [inclusive:exclusive] first3 := nums[:3] // [10, 20, 30] last2 := nums[3:] // [40, 50] middle := nums[1:4] // [20, 30, 40] // Append grows the slice nums = append(nums, 60, 70) // Iterate with index and value for i, v := range nums { fmt.Printf("nums[%d] = %d\n", i, v) } // 2D slice matrix := [][]int{ {1, 2, 3}, {4, 5, 6}, }

Maps

Operation Description Example
Create with literal Initialize map with values m := map[string]int{"a": 1, "b": 2}
Create with make Create empty map m := make(map[string]int)
Set value Add or update key m["key"] = 42
Get value Retrieve by key (zero value if missing) v := m["key"]
Check existence Comma-ok idiom v, ok := m["key"]
Delete key Remove entry (no-op if key absent) delete(m, "key")
Iterate Loop over all key-value pairs for k, v := range m { ... }
Length Number of entries n := len(m)
Nil map Read returns zero value; write panics var m map[string]int // m == nil
users := map[string]int{ "alice": 32, "bob": 28, } // Check if key exists if age, ok := users["alice"]; ok { fmt.Printf("Alice is %d\n", age) } // Delete a key delete(users, "bob") // Map of slices graph := map[string][]string{ "A": {"B", "C"}, "B": {"D"}, }
Tip: Map iteration order is randomized in Go. If you need sorted output, collect the keys into a slice, sort it, then iterate.

Structs & Methods

Pattern Description Example
Define struct Named collection of fields type User struct { Name string; Age int }
Create instance Initialize by field name u := User{Name: "Alice", Age: 30}
Pointer to struct Allocate on heap with & u := &User{Name: "Bob"}
Access fields Dot notation (auto-dereferences pointers) fmt.Println(u.Name)
Struct tags Metadata for encoding/reflection Name string `json:"name" validate:"required"`
Embedding Composition (promotes fields/methods) type Admin struct { User; Role string }
Value receiver Method on copy of struct func (u User) Greet() string
Pointer receiver Method can modify the struct func (u *User) SetAge(age int)
Anonymous struct Inline struct without a type name p := struct{ X, Y int }{10, 20}
Constructor pattern Factory function (Go has no constructors) func NewUser(name string) *User
type User struct { Name string `json:"name"` Email string `json:"email"` Age int `json:"age,omitempty"` } // Value receiver — doesn't modify the original func (u User) Greet() string { return "Hi, I'm " + u.Name } // Pointer receiver — can modify the struct func (u *User) SetAge(age int) { u.Age = age } // Embedding for composition type Admin struct { User // embedded — Admin inherits User's fields and methods Permissions []string } admin := Admin{ User: User{Name: "Alice", Email: "alice@dev.io"}, Permissions: []string{"read", "write"}, } fmt.Println(admin.Name) // "Alice" — promoted from User

Interfaces

Concept Description Example
Define interface Set of method signatures type Stringer interface { String() string }
Implicit implementation No "implements" keyword needed // Type satisfies interface if it has all methods
Empty interface Accepts any type (like any) func Print(v interface{}) { ... }
any Alias for interface{} (Go 1.18+) func Print(v any) { ... }
Type assertion Extract concrete type from interface s := i.(string)
Safe type assertion Assertion with ok check s, ok := i.(string)
Type switch Branch on underlying type switch v := i.(type) { case int: ... }
Interface embedding Compose interfaces type ReadWriter interface { Reader; Writer }
Stringer Implement String() for custom printing func (u User) String() string { ... }
type Shape interface { Area() float64 Perimeter() float64 } type Circle struct { Radius float64 } func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius } func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius } // Circle implicitly satisfies Shape var s Shape = Circle{Radius: 5} fmt.Println(s.Area()) // 78.5398... // Type assertion if c, ok := s.(Circle); ok { fmt.Println("Radius:", c.Radius) } // Type switch func describe(i interface{}) string { switch v := i.(type) { case int: return fmt.Sprintf("int: %d", v) case string: return fmt.Sprintf("string: %s", v) default: return "unknown" } }
Tip: Keep interfaces small. The Go standard library's io.Reader has just one method: Read(p []byte) (n int, err error). Small interfaces are easier to implement and compose.

Pointers

Operation Description Example
Declare pointer Pointer to a type var p *int
Address-of & Get memory address of variable p := &x
Dereference * Access value at pointer address fmt.Println(*p)
new() Allocate zero-valued memory, return pointer p := new(int) // *p == 0
Nil pointer Uninitialized pointer is nil var p *int // p == nil
Pointer to struct Auto-dereferenced with dot notation p := &User{Name: "Go"}
p.Name // no need for (*p).Name
No pointer arithmetic Go does not support pointer math (use unsafe if needed) // p++ is not allowed
func increment(p *int) { *p++ // modify the original value } x := 10 increment(&x) fmt.Println(x) // 11 // Pointer to struct type Config struct { Debug bool } cfg := &Config{Debug: true} cfg.Debug = false // auto-dereferenced

Goroutines & Channels

Concept Description Example
Goroutine Lightweight concurrent function go doWork()
Goroutine with closure Launch anonymous function concurrently go func() { ... }()
Unbuffered channel Synchronous send/receive ch := make(chan int)
Buffered channel Async up to buffer size ch := make(chan int, 10)
Send to channel Blocks if unbuffered/full ch <- 42
Receive from channel Blocks if empty val := <-ch
Directional channel Restrict to send-only or receive-only func send(ch chan<- int) { ch <- 1 }
Close channel Signal no more values will be sent close(ch)
Range over channel Receive until channel is closed for v := range ch { ... }
select Multiplex channel operations select { case v := <-ch1: ... case ch2 <- x: ... }
sync.WaitGroup Wait for a group of goroutines to finish var wg sync.WaitGroup
sync.Mutex Mutual exclusion lock var mu sync.Mutex
sync.Once Execute function exactly once once.Do(func() { ... })
context.Context Cancellation, deadlines, values for goroutines ctx, cancel := context.WithTimeout(...)
// Worker pool with goroutines and channels func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker %d processing job %d\n", id, j) time.Sleep(time.Second) results <- j * 2 } } func main() { jobs := make(chan int, 100) results := make(chan int, 100) // Start 3 workers for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // Send 5 jobs for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // Collect results for r := 1; r <= 5; r++ { fmt.Println(<-results) } } // WaitGroup pattern var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() fmt.Printf("goroutine %d\n", id) }(i) } wg.Wait() // blocks until all goroutines finish
Tip: Always pass loop variables as function arguments to goroutine closures to avoid data races. Use go vet and the race detector (go run -race) to catch concurrency bugs.

Error Handling

Pattern Description Example
error interface Built-in interface: Error() string func open(f string) (*File, error)
Check errors Always check returned errors if err != nil { return err }
errors.New() Create simple error err := errors.New("not found")
fmt.Errorf() Formatted error string err := fmt.Errorf("user %d: %w", id, err)
Error wrapping %w Wrap errors for context chain fmt.Errorf("open: %w", err)
errors.Is() Check error chain for specific value if errors.Is(err, os.ErrNotExist) { ... }
errors.As() Check error chain for specific type var pathErr *os.PathError
if errors.As(err, &pathErr) { ... }
Custom error type Struct implementing error interface type NotFoundError struct { ID int }
panic() Unrecoverable error (crashes program) panic("fatal: out of memory")
recover() Catch panic in deferred function defer func() { if r := recover(); r != nil { ... } }()
// Custom error type type ValidationError struct { Field string Message string } func (e *ValidationError) Error() string { return fmt.Sprintf("%s: %s", e.Field, e.Message) } // Wrapping errors for context func readConfig(path string) ([]byte, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("readConfig %s: %w", path, err) } return data, nil } // Checking wrapped errors _, err := readConfig("/etc/app.conf") if errors.Is(err, os.ErrNotExist) { fmt.Println("Config file missing — using defaults") } // Recover from panic func safeDiv(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("panic: %v", r) } }() return a / b, nil }

Packages & Imports

Pattern Description Example
Package declaration First line of every Go file package main
Single import Import one package import "fmt"
Grouped import Import multiple packages import (
  "fmt"
  "os"
)
Alias import Rename a package locally import f "fmt"
Blank import Import for side effects only import _ "image/png"
Dot import Import into current namespace (avoid) import . "math"
Exported names Capitalized = public, lowercase = private func DoWork() { ... } // exported
func helper() { ... } // unexported
Internal packages Only importable by parent tree myapp/internal/db
package main import ( "encoding/json" "fmt" "log" "net/http" "os" "time" "github.com/gorilla/mux" // third-party package ) func main() { r := mux.NewRouter() // ... }

String Manipulation

Function Description Example
strings.Contains(s, sub) Check if substring exists strings.Contains("hello", "ell") // true
strings.HasPrefix(s, p) Check if string starts with prefix strings.HasPrefix("hello", "he") // true
strings.HasSuffix(s, p) Check if string ends with suffix strings.HasSuffix("hello", "lo") // true
strings.Index(s, sub) Find first index of substring (-1 if not found) strings.Index("hello", "ll") // 2
strings.Replace(s, old, new, n) Replace first n occurrences (-1 for all) strings.Replace("foo", "o", "0", -1) // "f00"
strings.ReplaceAll(s, old, new) Replace all occurrences strings.ReplaceAll("aabb", "a", "x") // "xxbb"
strings.Split(s, sep) Split string into slice strings.Split("a,b,c", ",") // ["a","b","c"]
strings.Join(s, sep) Join slice into string strings.Join([]string{"a","b"}, "-") // "a-b"
strings.ToUpper(s) Convert to uppercase strings.ToUpper("hello") // "HELLO"
strings.ToLower(s) Convert to lowercase strings.ToLower("HELLO") // "hello"
strings.TrimSpace(s) Remove leading/trailing whitespace strings.TrimSpace(" hi ") // "hi"
strings.Trim(s, cutset) Remove specified leading/trailing chars strings.Trim("##hi##", "#") // "hi"
strings.Repeat(s, n) Repeat string n times strings.Repeat("ab", 3) // "ababab"
strings.Count(s, sub) Count non-overlapping occurrences strings.Count("hello", "l") // 2
strings.NewReader(s) Create io.Reader from string r := strings.NewReader("data")
strconv.Itoa(n) Int to string strconv.Itoa(42) // "42"
strconv.Atoi(s) String to int n, err := strconv.Atoi("42")
fmt.Sprintf() Format string (like printf) s := fmt.Sprintf("name=%s age=%d", n, a)
import ("fmt"; "strings"; "strconv") // String builder for efficient concatenation var b strings.Builder for i := 0; i < 100; i++ { fmt.Fprintf(&b, "item %d, ", i) } result := b.String() // Multiline raw string literal query := `SELECT id, name FROM users WHERE active = true ORDER BY name` // Rune iteration (for Unicode correctness) for i, r := range "Hello, 世界" { fmt.Printf("byte %d: %c (U+%04X)\n", i, r, r) }

File I/O

Operation Description Example
os.ReadFile(path) Read entire file into []byte data, err := os.ReadFile("f.txt")
os.WriteFile(path, data, perm) Write []byte to file os.WriteFile("f.txt", data, 0644)
os.Open(path) Open file for reading f, err := os.Open("f.txt")
os.Create(path) Create or truncate file for writing f, err := os.Create("f.txt")
os.OpenFile(path, flag, perm) Open with specific flags (append, etc.) os.OpenFile("f.txt", os.O_APPEND|os.O_WRONLY, 0644)
f.Close() Close file (always defer this) defer f.Close()
bufio.Scanner Read file line by line scanner := bufio.NewScanner(f)
bufio.Writer Buffered writes w := bufio.NewWriter(f)
io.Copy(dst, src) Copy from Reader to Writer io.Copy(os.Stdout, resp.Body)
os.Mkdir(path, perm) Create directory os.Mkdir("data", 0755)
os.MkdirAll(path, perm) Create directory tree os.MkdirAll("a/b/c", 0755)
os.Remove(path) Delete file or empty directory os.Remove("f.txt")
os.Stat(path) Get file info (size, mode, modtime) info, err := os.Stat("f.txt")
filepath.Walk() Recursively walk directory tree filepath.Walk(".", walkFn)
// Read file line by line f, err := os.Open("data.txt") if err != nil { log.Fatal(err) } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() fmt.Println(line) } // Write JSON to file type Config struct { Host string `json:"host"` Port int `json:"port"` } cfg := Config{Host: "localhost", Port: 8080} data, _ := json.MarshalIndent(cfg, "", " ") os.WriteFile("config.json", data, 0644)

Common Standard Library

fmt - Formatted I/O

Function Description Example
fmt.Println() Print with newline fmt.Println("hello", 42)
fmt.Printf() Formatted print (%s %d %v %T %+v) fmt.Printf("name=%s age=%d\n", n, a)
fmt.Sprintf() Return formatted string s := fmt.Sprintf("%d items", count)
fmt.Fprintf() Write formatted to io.Writer fmt.Fprintf(os.Stderr, "error: %v\n", err)
fmt.Errorf() Return formatted error fmt.Errorf("failed: %w", err)

fmt Verbs (Format Specifiers)

Verb Description Example Output
%vDefault format{Alice 30}
%+vWith field names{Name:Alice Age:30}
%#vGo syntax representationmain.User{Name:"Alice", Age:30}
%TType of valuemain.User
%dInteger (decimal)42
%x / %o / %bHex / octal / binary2a / 52 / 101010
%fFloat (default precision)3.141593
%.2fFloat with 2 decimal places3.14
%sStringhello
%qQuoted string"hello"
%pPointer address0xc0000b2000
%wWrap error (Errorf only)-

net/http - HTTP Server & Client

// Simple HTTP server func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:]) } http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) // HTTP GET request resp, err := http.Get("https://api.example.com/data") if err != nil { log.Fatal(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) // HTTP POST with JSON payload := strings.NewReader(`{"name":"Go"}`) resp, err := http.Post("https://api.example.com/users", "application/json", payload) // Custom HTTP client with timeout client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Get("https://api.example.com")

encoding/json - JSON Encoding/Decoding

type User struct { Name string `json:"name"` Email string `json:"email"` Age int `json:"age,omitempty"` // omit if zero Pass string `json:"-"` // always omit Tags []string `json:"tags"` } // Marshal (struct to JSON) u := User{Name: "Alice", Email: "a@b.com"} jsonBytes, err := json.Marshal(u) jsonPretty, _ := json.MarshalIndent(u, "", " ") // Unmarshal (JSON to struct) var user User err := json.Unmarshal(jsonBytes, &user) // Decode from io.Reader (e.g., HTTP response body) var user User err := json.NewDecoder(resp.Body).Decode(&user) // Encode to io.Writer err := json.NewEncoder(os.Stdout).Encode(user) // Dynamic JSON with map var data map[string]interface{} json.Unmarshal(jsonBytes, &data)

time - Time & Duration

// Current time now := time.Now() fmt.Println(now.Year(), now.Month(), now.Day()) // Format (uses reference time: Mon Jan 2 15:04:05 MST 2006) s := now.Format("2006-01-02 15:04:05") s = now.Format(time.RFC3339) // "2024-03-15T10:30:00Z" // Parse a time string t, err := time.Parse("2006-01-02", "2024-12-25") // Duration d := 5 * time.Second time.Sleep(100 * time.Millisecond) // Timer and Ticker timer := time.NewTimer(2 * time.Second) <-timer.C // blocks for 2s ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for t := range ticker.C { fmt.Println("tick at", t) } // Measure elapsed time start := time.Now() doWork() elapsed := time.Since(start) fmt.Printf("Took %s\n", elapsed)
Tip: Go uses the reference time Mon Jan 2 15:04:05 MST 2006 (01/02 03:04:05 '06 -0700) for formatting. This is a mnemonic: 1-2-3-4-5-6-7. Unlike most languages, you don't use YYYY-MM-DD.

os - Operating System Interface

Function Description Example
os.Args Command-line arguments args := os.Args[1:]
os.Getenv(key) Get environment variable home := os.Getenv("HOME")
os.Setenv(key, val) Set environment variable os.Setenv("PORT", "8080")
os.Exit(code) Exit with status code os.Exit(1)
os.Getwd() Get working directory dir, _ := os.Getwd()
os.Stdin/Stdout/Stderr Standard I/O file descriptors fmt.Fprintln(os.Stderr, "error")

Go Modules

Command Description Example
go mod init Initialize a new module (creates go.mod) go mod init github.com/user/project
go get Add/update dependency go get github.com/gorilla/mux@latest
go mod tidy Add missing, remove unused dependencies go mod tidy
go mod download Download dependencies to local cache go mod download
go mod vendor Copy deps into vendor/ directory go mod vendor
go.mod Module definition file module github.com/user/project
go 1.22
require github.com/lib/pq v1.10.9
go.sum Cryptographic checksums for dependencies // Auto-generated, commit to version control
go build Compile packages and dependencies go build -o myapp ./cmd/server
go run Compile and run go run main.go
go test Run tests go test ./... -v -race
go fmt Format source code go fmt ./...
go vet Report likely bugs go vet ./...
go install Compile and install binary to $GOPATH/bin go install github.com/user/tool@latest
Cross-compile Build for different OS/arch GOOS=linux GOARCH=amd64 go build
# Initialize a new project mkdir myapp && cd myapp go mod init github.com/username/myapp # Add a dependency go get github.com/gin-gonic/gin@latest # Run tests with race detector and coverage go test ./... -race -coverprofile=coverage.out go tool cover -html=coverage.out # Build for multiple platforms GOOS=linux GOARCH=amd64 go build -o myapp-linux GOOS=darwin GOARCH=arm64 go build -o myapp-mac GOOS=windows GOARCH=amd64 go build -o myapp.exe # Common project layout myapp/ cmd/ server/main.go # entry points internal/ # private packages handler/ service/ pkg/ # public packages go.mod go.sum