A data type tells Go what kind of value a variable holds — a number, some text, a true/false, and so on. Go is statically typed, so every value has a type, and the compiler checks it.
Let’s go through the basic types first, then hit the big interview favorite: zero values.
The basic types
var i int = 42 // platform-sized integer (32 or 64 bit)
var big int64 = 99999 // explicitly 64-bit integer
var price float64 = 9.99 // floating-point number (use float64 by default)
var name string = "Go" // text
var ok bool = true // true or false
var b byte = 'A' // alias for uint8 — a single raw byte (65)
var r rune = '日' // alias for int32 — a single Unicode character
A few notes that trip people up:
intsizes itself to the machine (64-bit on modern systems). When in doubt, just useint.float64is the default float — prefer it overfloat32unless we have a memory reason.byteis just a nicer name foruint8.runeis just a nicer name forint32. They exist to make intent clear.
byte vs rune (the string gotcha)
In simple language, a byte is one raw 8-bit chunk, while a rune is one full character (which might be several bytes).
This matters because Go strings are UTF-8 encoded. An emoji or a Hindi character takes multiple bytes but is a single rune.
s := "héllo"
fmt.Println(len(s)) // 6 — counts BYTES, not characters! (é is 2 bytes)
fmt.Println(len([]rune(s))) // 5 — converting to runes counts CHARACTERS
for i, r := range s {
// range over a string gives us runes, not bytes
fmt.Printf("%d: %c\n", i, r)
}
So len(string) gives bytes, not character count. Remember that — it’s a classic gotcha.
The zero value concept
Here’s the Go-specific idea interviewers love. In Go, every variable is automatically given a “zero value” if we don’t initialize it. There’s no such thing as an uninitialized variable holding garbage memory.
Think of it like this: Go refuses to hand us a box with random junk inside. It always gives us a clean, sensible default.
This kills a whole category of bugs. In C, an uninitialized int could be any random number. In Java, an uninitialized object is null and blows up. In Go, things just start at a safe default.
Here’s what each type defaults to:
var n int // 0
var f float64 // 0.0
var s string // "" (empty, not nil!)
var ready bool // false
var p *int // nil
fmt.Println(n, f, s == "", ready, p == nil) // 0 0 true false true
Notice that a string’s zero value is the empty string "", not nil. Only the reference-y types (pointers, slices, maps, channels, funcs, interfaces) are nil.
This means we can declare a variable and start using it safely. For example, a zero-value int is ready to be added to, and a zero-value bool is already false — no setup needed.
Interview soundbite
Go has the usual basic types, plus byte (alias for uint8) and rune (alias for int32) for working with bytes versus full Unicode characters in strings. The killer concept is zero values: every variable gets a sane default automatically — 0 for numbers, "" for strings, false for bools, and nil for reference types — so there’s no such thing as an uninitialized garbage value in Go.