Section 02
Types & Variables
Go is statically typed. Types are explicit, integer sizes are explicit, and every variable has a zero value — there is no uninitialised state.
Variable declaration — four forms
Java — declaration
int x = 10;
int y; // y = 0 (primitive)
String s; // s = null (object!)
var z = 10; // Java 10+ local varGo — four equivalent forms
var x int = 10 // explicit type + value
var y int // zero value: 0 (never null)
var s string // zero value: "" (never null)
z := 10 // := infers type, only inside functions
// Go has NO null for value types
// Zero values are always valid, usable defaultsWhy Go does thisJava objects can be null, causing NullPointerExceptions. Go value types always have a zero value. Only pointers, slices, maps, and interfaces can be nil — and you know which ones those are because you declared them that way.
Integer types — size is explicit
go — integer types, pick intentionally
// Java has: byte(8), short(16), int(32), long(64) — all signed
// Go has signed AND unsigned, explicitly named by bit width:
var a int // platform-sized: 64-bit on 64-bit OS — default choice
var b int8 // -128 to 127 — rare
var c int16 // -32768 to 32767 — rare
var d int32 // ±2 billion — alias: rune (Unicode code points)
var e int64 // ±9 quintillion — DB IDs, Unix timestamps
var f uint // unsigned platform-sized — loop bounds etc
var g uint8 // 0–255 — alias: byte (binary data, buffers, payloads)
var h uint64 // 0–18 quintillion — file sizes, memory offsets
// Quick reference:
// int = general purpose counter / index
// int64 = database primary key, Unix timestamp (time.Now().Unix())
// byte = one octet of binary data ([]byte is a byte slice)
// rune = one Unicode character (range over string gives runes)ℹ
byte and uint8 are identical — just different names expressing intent. Same for rune and int32. The name you use tells the reader what the value represents.Named types and enums with iota
Java — enum
public enum Status {
IDLE, ACTIVE, DRAINING, STOPPED
}
Status s = Status.ACTIVE;Go — named type + iota
// Create a named type — distinct from plain int
type Status int
const (
StatusIdle Status = iota // 0 — iota starts at 0
StatusActive // 1 — auto-increments
StatusDraining // 2
StatusStopped // 3
)
var s Status = StatusActive
// Named type prevents accidental mixing:
func SetStatus(s Status) {}
SetStatus(StatusActive) // ok
SetStatus(42) // ok — untyped constant, implicitly converts
var i int = 1
SetStatus(i) // compile error — int ≠ StatusWhy Go does thisGo has no enum keyword. Instead, a named type over int plus iota constants gives you the same safety. The compiler treats
Status and int as different types — you cannot accidentally pass a raw integer where a Status is expected.