Skip to content

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:

  • int vs int64: plain int is 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.)
  • rune vs byte: single quotes make a rune ('a'), a Unicode code point. byte is 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 := vs var and when each is used
  • [ ] You know what a zero value is and why it matters
  • [ ] You can append to a slice and look up a map key safely

Next: Control Flow.