Go Cheat Sheets
Quick-reference guides for Go syntax, the standard library, and common idioms.
Variables, Constants & iota
// Variable declarations
var x int = 42
var s string // zero value: ""
var b bool // zero value: false
// Short declaration (inside functions only)
y := 3.14
name, age := "Alice", 30
// Constants
const Pi = 3.14159
const MaxSize = 1 << 20 // 1 MB
// iota in a const block
type Direction int
const (
North Direction = iota // 0
East // 1
South // 2
West // 3
)
type ByteSize float64
const (
_ = iota // discard first value
KB ByteSize = 1 << (10 * iota) // 1024
MB // 1048576
GB
)Functions
// Multiple return values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
// Named return values
func minMax(nums []int) (min, max int) {
min, max = nums[0], nums[0]
for _, n := range nums[1:] {
if n < min { min = n }
if n > max { max = n }
}
return // naked return
}
// Variadic function
func sum(ns ...int) int {
total := 0
for _, n := range ns {
total += n
}
return total
}
sum(1, 2, 3)
nums := []int{1, 2, 3}
sum(nums...) // spread slice
// Closure
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
c() // 1
c() // 2Control Flow
// for — the only loop keyword
for i := 0; i < 10; i++ { }
for i < 10 { } // while equivalent
for { } // infinite loop
for i, v := range slice { }
for k, v := range m { } // map
for ch := range channel { } // receive until closed
// if / else
if x > 0 {
fmt.Println("positive")
} else if x < 0 {
fmt.Println("negative")
} else {
fmt.Println("zero")
}
// if with initialiser
if err := doWork(); err != nil {
log.Fatal(err)
}
// switch — no fallthrough by default
switch x {
case 1:
fmt.Println("one")
case 2, 3:
fmt.Println("two or three")
default:
fmt.Println("other")
}
// switch on type (type switch)
switch v := i.(type) {
case int:
fmt.Printf("int: %d\n", v)
case string:
fmt.Printf("string: %s\n", v)
default:
fmt.Printf("unknown: %T\n", v)
}
// select — for channels
select {
case msg := <-ch:
fmt.Println(msg)
case ch <- "hello":
fmt.Println("sent")
default:
fmt.Println("no channel ready")
}Types: Arrays, Slices, Maps, Structs
// Array — fixed size
var a [3]int // [0 0 0]
b := [3]int{1, 2, 3}
c := [...]int{1, 2, 3} // compiler counts
// Slice — dynamic view of an array
s := []int{1, 2, 3}
s = append(s, 4, 5)
s2 := s[1:3] // [2 3] — shares memory
cp := make([]int, 5) // len=5, cap=5
copy(cp, s)
// Map
m := map[string]int{"a": 1, "b": 2}
m["c"] = 3
v, ok := m["x"] // ok=false if missing
delete(m, "a")
// Struct
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
p.Age = 31
pp := &Person{Name: "Bob"} // pointer to struct
// Embedded struct
type Employee struct {
Person // promoted fields
Company string
}
e := Employee{Person: Person{Name: "Carol"}, Company: "Gophers Inc."}
fmt.Println(e.Name) // e.Person.Name promoted
// Interface
type Stringer interface {
String() string
}
var s Stringer = p // if Person has String() string methodPointers
x := 42
p := &x // pointer to x
*p = 100 // dereference to update x
fmt.Println(x) // 100
// Pointer receiver — mutates the value
func (p *Person) Birthday() {
p.Age++
}
// new — allocates zeroed value, returns pointer
n := new(int) // *int, *n == 0fmt — Formatting & I/O
import "fmt"
// Common verbs
fmt.Printf("%v", val) // default format
fmt.Printf("%+v", val) // struct with field names
fmt.Printf("%#v", val) // Go syntax representation
fmt.Printf("%T", val) // type
fmt.Printf("%d", n) // integer
fmt.Printf("%f", f) // float (%.2f for 2 decimals)
fmt.Printf("%s", s) // string
fmt.Printf("%q", s) // quoted string
fmt.Printf("%t", b) // boolean
fmt.Printf("%p", ptr) // pointer address
fmt.Printf("%b", n) // binary
fmt.Printf("%x", n) // hexadecimal
// Construct strings
s := fmt.Sprintf("hello, %s!", name)
fmt.Fprintln(os.Stderr, "error:", err) // write to writererrors — Error Handling
import "errors"
// Create errors
err1 := errors.New("something went wrong")
err2 := fmt.Errorf("open %s: %w", path, err) // wrap with %w
// Inspect error chains
if errors.Is(err, os.ErrNotExist) { }
var pathErr *os.PathError
if errors.As(err, &pathErr) {
fmt.Println(pathErr.Path)
}strings — String Operations
import "strings"
strings.Contains(s, "sub")
strings.HasPrefix(s, "pre")
strings.HasSuffix(s, "suf")
strings.Index(s, "sub") // -1 if not found
strings.Count(s, "sub")
strings.ToUpper(s)
strings.ToLower(s)
strings.TrimSpace(s)
strings.Trim(s, "xy")
strings.Split(s, ",") // []string
strings.Join(parts, ",")
strings.ReplaceAll(s, "old", "new")
strings.Fields(s) // split by whitespace
// Efficient concatenation
var b strings.Builder
b.WriteString("hello")
b.WriteString(" world")
result := b.String()strconv — Type Conversions
import "strconv"
n, err := strconv.Atoi("42") // string → int
s := strconv.Itoa(42) // int → string
f, err := strconv.ParseFloat("3.14", 64)
i, err := strconv.ParseInt("ff", 16, 64) // base 16
b, err := strconv.ParseBool("true")
strconv.FormatFloat(3.14, 'f', 2, 64) // "3.14"
strconv.FormatInt(255, 16) // "ff"io / os — I/O Primitives
import ("io"; "os")
// Read entire file
data, err := os.ReadFile("file.txt") // []byte
err = os.WriteFile("out.txt", data, 0644)
// Open file
f, err := os.Open("file.txt") // read-only
defer f.Close()
buf, _ := io.ReadAll(f)
// Create / write
f, err = os.Create("out.txt")
f.WriteString("hello\n")
// Discard all reads
io.Copy(io.Discard, r)net/http — HTTP Client & Server
import "net/http"
// Simple server
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, Go!")
})
http.ListenAndServe(":8080", nil)
// Custom handler (with mux)
mux := http.NewServeMux()
mux.HandleFunc("GET /api/items", handleItems)
http.ListenAndServe(":8080", mux)
// HTTP client
resp, err := http.Get("https://example.com")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
// POST with body
req, _ := http.NewRequestWithContext(ctx, "POST", url, body)
req.Header.Set("Content-Type", "application/json")
resp, err = http.DefaultClient.Do(req)encoding/json — JSON
import "encoding/json"
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age,omitempty"` // omit if zero
pass string // unexported — not marshalled
}
// Marshal (Go → JSON)
data, err := json.Marshal(User{ID: 1, Name: "Alice"})
// {"id":1,"name":"Alice"}
// Unmarshal (JSON → Go)
var u User
err = json.Unmarshal([]byte(`{"id":2,"name":"Bob"}`), &u)
// Stream encode / decode
enc := json.NewEncoder(w)
enc.Encode(u)
dec := json.NewDecoder(r.Body)
dec.Decode(&u)sync — Concurrency Primitives
import "sync"
// Mutex
var mu sync.Mutex
mu.Lock()
// critical section
mu.Unlock()
defer mu.Unlock() // idiomatic
// RWMutex — concurrent reads
var rw sync.RWMutex
rw.RLock(); rw.RUnlock()
rw.Lock(); rw.Unlock()
// WaitGroup
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item Item) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait()
// Once — run exactly once
var once sync.Once
once.Do(func() { initExpensiveThing() })
// Map — concurrent-safe map
var m sync.Map
m.Store("key", 42)
v, ok := m.Load("key")
m.Range(func(k, v any) bool {
fmt.Println(k, v)
return true // continue
})context — Cancellation & Deadlines
import "context"
// Root contexts
ctx := context.Background() // top-level, never cancelled
ctx := context.TODO() // placeholder
// Derive with cancellation
ctx, cancel := context.WithCancel(parent)
defer cancel() // always call cancel
// Derive with timeout
ctx, cancel := context.WithTimeout(parent, 5*time.Second)
defer cancel()
// Derive with deadline
ctx, cancel := context.WithDeadline(parent, time.Now().Add(time.Minute))
defer cancel()
// Store / retrieve values (use typed keys to avoid collisions)
type ctxKey string
ctx = context.WithValue(ctx, ctxKey("userID"), 42)
id := ctx.Value(ctxKey("userID")).(int)
// React to cancellation
select {
case <-ctx.Done():
return ctx.Err() // context.Canceled or context.DeadlineExceeded
case result := <-work:
return result
}Error Handling Patterns
// Basic sentinel check
if err != nil {
return fmt.Errorf("doWork: %w", err)
}
// Wrap with context
func loadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("loadConfig: %w", err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("loadConfig: decode: %w", err)
}
return &cfg, nil
}
// Sentinel errors
var ErrNotFound = errors.New("not found")
if errors.Is(err, ErrNotFound) {
// handle specifically
}
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("invalid field:", ve.Field)
}Table-Driven Tests
func TestAdd(t *testing.T) {
cases := []struct {
name string
a, b int
expected int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := Add(tc.a, tc.b)
if got != tc.expected {
t.Errorf("Add(%d, %d) = %d; want %d", tc.a, tc.b, got, tc.expected)
}
})
}
}Functional Options Pattern
type Server struct {
host string
port int
timeout time.Duration
}
type Option func(*Server)
func WithHost(host string) Option {
return func(s *Server) { s.host = host }
}
func WithPort(port int) Option {
return func(s *Server) { s.port = port }
}
func WithTimeout(d time.Duration) Option {
return func(s *Server) { s.timeout = d }
}
func NewServer(opts ...Option) *Server {
s := &Server{host: "localhost", port: 8080, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage
srv := NewServer(
WithHost("0.0.0.0"),
WithPort(9090),
WithTimeout(time.Minute),
)Struct Embedding for Composition
type Logger struct {
prefix string
}
func (l *Logger) Log(msg string) {
fmt.Printf("[%s] %s\n", l.prefix, msg)
}
type Service struct {
Logger // promoted: Service.Log is available
db *sql.DB
}
svc := &Service{Logger: Logger{prefix: "svc"}}
svc.Log("started") // calls svc.Logger.Log
// Embedding an interface satisfies it
type ReadWriter struct {
io.Reader
io.Writer
}Interface Guard
// Compile-time check: MyWriter must implement io.Writer.
// If it doesn't, this line fails to compile — no runtime surprise.
var _ io.Writer = (*MyWriter)(nil)
// Same pattern for multiple interfaces
var _ interface {
io.Reader
io.Writer
} = (*MyReadWriter)(nil)Common Concurrency Patterns
// Fan-out: distribute work across N goroutines
jobs := make(chan Job, 100)
for range workers {
go func() {
for job := range jobs {
process(job)
}
}()
}
// Pipeline stage
func generate(nums ...int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for _, n := range nums { out <- n }
}()
return out
}
// Timeout with select
select {
case result := <-work:
return result, nil
case <-time.After(5 * time.Second):
return nil, errors.New("timed out")
case <-ctx.Done():
return nil, ctx.Err()
}
// Try-send (non-blocking)
select {
case ch <- value:
default:
// channel full; drop or handle
}