1. The type system
- Statically typed — every variable has a fixed type; no implicit conversions between numeric types.
- Short declaration
:=— infer type, must declare at least one new var. varwith explicit type — also fine;var x int = 5.- Multiple declaration / assignment:
a, b := 1, 2; parallel assignmenta, b = b, aswaps without temp. - Untyped constants — adopt the context type when used (
x := 5→ int;f := 5.0→ float64). - Interfaces are the exception: they can hold any concrete type.
2. Zero values
Every declared variable starts at its zero value — no null in Go:
| Type | Zero value |
|---|---|
int, float | 0 / 0.0 |
bool | false |
string | "" |
| pointer / interface / map / slice / func / channel | nil |
| struct | all fields zeroed |
Interview point: zero values make Go memory zero-initialized — safe to use without explicit setup.
3. Pointers vs values
&x→ address;*p→ dereference.- Pointers cannot point to nothing;
nilpointer dereference panics. - A pointer
*intdiffers from a valueintin the type system — method receivers and interfaces care.
x := 10
p := &x
*p = 20
fmt.Println(x, *p) // 20 20
- When to use a pointer: mutate caller data, share large structs, indicate optional/missing.
- Slices/maps are reference-like already — copying a slice header copies the pointer.
4. Structs
- Fields, tags, embedding.
- Struct comparison — comparable only between identical types; never across structs.
- A struct with slices/maps inside is not comparable with
==(only comparable tonil). - Method on struct: value receiver vs pointer receiver (see Part 2).
type Point struct{ X, Y int }
a := Point{1, 2}
b := Point{1, 2}
fmt.Println(a == b) // true — all fields equal
- Unexported fields (lowercase) are private to the package; export with capital first letter.
%+vshows field names; empty structstruct{}(akastruct{}{}) is zero-size, useful as signal in channels.
4. Runes
stringis a byte slice — on the UTF-8 encoding of Unicode.rune=int32— one Unicode code point.len(s)counts bytes, not Runes;utf8.RuneCountInStringfor character count.for rangeover a string iterates runes, not bytes.'A'is a rune literal;"A"is a string.
s := "héllo"
fmt.Println(len(s)) // 6 bytes
fmt.Println(len([]rune(s))) // 5 runes
Gotcha: indexing/slicing a string operates on bytes — slicing mid-rune can produce invalid UTF-8.
5. Interview checkpoint
- Zero value vs
nilvs empty. &/*semantics; pointer vs value copy.- Rune vs byte;
len()byte vs rune count. - Escape analysis / heap vs stack allocation and where pointers commonly live.
- Struct value vs pointer slices — when each is idiomatic.
- Untyped constants in numeric expressions.
Premium Content
Unlock Part 1: Types, Zero Values & Pointers and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans