skip to content
Sandip's Blog
Table of Contents

Even if you “know the basics,” most gaps hide here. Make sure you can explain each item without looking it up.

Checklist

Types and variables

  • var, :=, const, iota
  • Zero values for every type (this is core to Go design)
  • Basic types: int, int64, uint8, float64, string, bool, byte, rune
  • Type conversion (Go has no implicit conversion)
  • Untyped constants
  • Shadowing, and how it causes bugs with :=

Strings, bytes, runes

  • A string is an immutable byte slice (UTF-8)
  • len(s) counts bytes, not characters
  • Iterating with for i, r := range s yields runes
  • strings.Builder for efficient concatenation

Control flow

  • for is the only loop (three forms plus range)
  • range over slices, maps, strings, channels, integers (for i := range 10), functions (Go 1.23+)
  • switch (no fallthrough by default), type switch, expressionless switch
  • defer: order (LIFO), argument evaluation time, use with loops
  • goto, labels, break/continue with labels
  • Loop variable semantics (changed in Go 1.22: per-iteration variables)

Functions

  • Multiple returns, named returns, variadic functions
  • First-class functions, closures, and what they capture
  • init() functions and package initialization order

Arrays, slices, maps (very important)

  • Array vs slice: arrays are values, slices are descriptors
  • Slice internals: pointer, length, capacity
  • append behavior and when it reallocates
  • Slices sharing a backing array, and the bugs this causes
  • Full slice expression s[a:b:c]
  • copy, clear, slices and maps packages
  • Map: unordered, nil map write panics, comma-ok idiom, not safe for concurrent writes
  • Deleting while iterating is safe in Go

Pointers

  • & and *, no pointer arithmetic
  • When to use pointer vs value (receivers, params)
  • new vs &T{}
  • Escape analysis (stack vs heap): conceptually

Structs and methods

  • Struct literals, embedded structs, struct tags
  • Value receiver vs pointer receiver rules
  • Method sets (why a T may not satisfy an interface but *T does)
  • Struct comparison and use as map keys

Visual: what append does

flowchart TD
  A["append(s, x)"] --> B{"len(s) < cap(s)?"}
  B -- "yes" --> C["Write x into the SAME backing array"]
  B -- "no" --> D["Allocate a NEW, larger array"]
  D --> E["Copy old elements, then add x"]
  C --> F["Other slices sharing this array can see the change"]
  E --> G["Returned slice points to the new array"]

This is why the first self-test question below prints what it does.

Self-test questions

  1. What does this print? Why?
    s := []int{1, 2, 3}
    t := s[:2]
    t = append(t, 99)
    fmt.Println(s)
  2. Why can’t you take the address of a map element?
  3. What is the output of a defer inside a loop of 3 iterations?
  4. When is a nil slice different from an empty slice?

Practice


Previous: Go Mastery Roadmap: From Basics to Production
Next: Go Mastery 2: Interfaces, Errors, Generics, Modules

Back to the roadmap