Variables and Types
Scope: declaring variables (:= vs var), the types you'll
use 95% of the time, and zero values. All examples were compiled
and run.
The short declaration: :=
name := "Ada"
age := 36
:= declares and assigns, and Go figures out the type. This is
what you'll write most of the time, inside functions.
var: the long form
var name string = "Ada"
var age int
var lets you declare without assigning — and spells out the
type. var age int gives you an int holding... what? Zero.
Go initializes every variable to its type's zero value:
| Type | Zero value |
|---|---|
| Numbers | 0 |
| Strings | "" (empty) |
| Booleans | false |
| Everything else | nil (Go's "nothing here") |
There's no such thing as an uninitialized variable in Go. This eliminates a whole class of bugs where you read garbage memory.
When to use which: := inside functions for brevity; var
at package level (where := isn't allowed) or when you want the
zero value explicitly.
Constants
const MaxUsers = 100
const values are fixed at compile time. Note the capital M:
capitalized names are exported (visible to other packages);
lowercase names are private to their package. This one rule
replaces public/private keywords entirely.
The types you'll actually use
| Type | Meaning | Example |
|---|---|---|
int |
Integer (64-bit on modern machines) | n := 42 |
int64, int32 |
Fixed-size integers | var big int64 = 9000000000 |
float64 |
Decimal numbers | pi := 3.14159 |
string |
Text (immutable, UTF-8) | s := "hello" |
bool |
true/false | done := false |
byte |
Alias for uint8; one raw byte |
b := byte('a') |
rune |
Alias for int32; one character |
r := '🦀' |
Notes:
intvsint64: plainintis the natural size for your machine (64 bits on anything modern). Use sized types when a format demands it.- Strings are immutable: you can't change one character of a
string; you build a new string. (Concatenation with
+is fine for small jobs.) runevsbyte: single quotes make arune('a'), a Unicode code point.byteis for raw data.
Slices: Go's growable lists
nums := []int{1, 2, 3}
nums = append(nums, 4)
fmt.Println(nums) // [1 2 3 4]
[]int is a slice: a growable list of ints. append returns
the updated slice — always assign it back (nums = append(...)),
because append may return a new underlying array.
Fixed-size arrays ([3]int) exist but are rare in practice;
slices are the default.
Maps: key-value lookup
ages := map[string]int{
"Ada": 36,
"Bob": 41,
}
fmt.Println(ages["Ada"]) // 36
map[string]int maps strings to ints. Looking up a missing key
returns the zero value (0 here) — no error, no crash. To check
whether a key exists:
age, ok := ages["Zed"]
if ok {
fmt.Println(age)
}
The value, ok pattern is idiomatic Go; you'll see it everywhere.
Check
- [ ] You can explain
:=vsvarand when each is used - [ ] You know what a zero value is and why it matters
- [ ] You can
appendto a slice and look up a map key safely
Next: Control Flow.