Data Types in Go
Go is statically typed — every variable has a type known at compile time. No implicit type coercion between different types.
1. Type Categories
| Category | Types | Behaviour |
|---|---|---|
| Basic | bool, int*, uint*, float*, complex*, string, byte, rune | Value type — copied on assignment |
| Composite | array, struct | Value type — fully copied |
| Reference | slice, map, channel, pointer, func | Header copied, underlying data shared |
| Interface | interface{} / any | Holds type + value pair |
2. Numeric Types
| Type | Size (bits) | Range | Use when |
|---|---|---|---|
int | 32 or 64 | platform-dependent | general integers — default choice |
int8 | 8 | -128 to 127 | tight memory constraints |
int16 | 16 | -32 768 to 32 767 | protocol fields |
int32 / rune ⭐ | 32 | -2³¹ to 2³¹-1 | Unicode code point |
int64 | 64 | -2⁶³ to 2⁶³-1 | timestamps, large IDs |
uint8 / byte ⭐ | 8 | 0 to 255 | raw bytes, image pixels |
uint16 | 16 | 0 to 65 535 | ports, small counts |
uint32 | 32 | 0 to 2³²-1 | IPv4, file sizes |
uint64 | 64 | 0 to 2⁶⁴-1 | large counters |
float32 | 32 | ±1.18e-38 to ±3.4e38 | graphics, sensors |
float64 | 64 | ±2.23e-308 to ±1.8e308 | default float — always prefer |
complex64 | 64 | float32 parts | scientific computing |
complex128 | 128 | float64 parts | scientific computing |
Rule: Use
intfor integers,float64for floats, unless you have a specific reason to use a smaller type.
3. Other Basic Types
var b bool = true // false by default
var s string = "Hello, Go" // "" by default, immutable
var r rune = 'A' // int32 alias — Unicode code point
var by byte = 255 // uint8 alias — raw byte4. Zero Values ⭐
Go always initialises variables — there is no garbage/undefined value.
| Type | Zero Value |
|---|---|
int, int8 … int64 | 0 |
uint, byte … uint64 | 0 |
float32, float64 | 0.0 |
bool | false |
string | "" (empty, not nil) |
pointer, slice, map, channel, func | nil |
struct | all fields set to their zero values |
array | all elements set to their zero values |
var i int // 0
var f float64 // 0.0
var s string // ""
var b bool // false
var p *int // nil5. Variable Declaration
// Full form — explicit type
var name string = "Go"
// Type inferred from value
var name = "Go"
// Short declaration — inside functions only
name := "Go"
// Multiple variables
var x, y int = 1, 2
a, b := 10, "hello"
// Block declaration
var (
host string = "localhost"
port int = 8080
tls bool = true
)6. Type Conversion
Go has no implicit conversion — all conversions are explicit.
var i int = 42
var f float64 = float64(i) // must be explicit
var u uint = uint(f)
// string ↔ int — NOT with a cast, use strconv
s := strconv.Itoa(42) // int → string "42"
n, err := strconv.Atoi("42") // string → int 42
// string(65) converts a rune, NOT an integer to its digits
fmt.Println(string(65)) // "A" ← common mistake!
fmt.Println(strconv.Itoa(65)) // "65" ← correct⚠️ Interview trap:
string(65)produces"A"(rune 65 = ‘A’), not"65". Usestrconv.Itoato get digits.
7. fmt Formatting Verbs
General
| Verb | Description | Example output |
|---|---|---|
%v | Default format | {John 25} |
%+v | Struct with field names | {Name:John Age:25} |
%#v | Go syntax representation | main.Person{Name:"John"} |
%T ⭐ | Type of the value | string, int, []int |
%% | Literal % sign | % |
Integers
| Verb | Format | 42 → |
|---|---|---|
%d | Decimal | 42 |
%b | Binary | 101010 |
%o | Octal | 52 |
%x | Hex lowercase | 2a |
%X | Hex uppercase | 2A |
Floats
| Verb | Format | 3.14159 → |
|---|---|---|
%f | Decimal point | 3.141590 |
%.2f | Decimal, 2 places | 3.14 |
%e | Scientific (e) | 3.141593e+00 |
%g | Compact (e or f) | 3.14159 |
Strings & Runes
| Verb | Format | Example output |
|---|---|---|
%s | Plain string | hello |
%q | Quoted string | "hello" |
%c ⭐ | Unicode character | A (from 65) |
%U | Unicode code point | U+0041 |
%p | Pointer address | 0xc000010050 |
n := 42
fmt.Printf("%d %b %o %x %X\n", n, n, n, n, n)
// 42 101010 52 2a 2A
pi := math.Pi
fmt.Printf("%f %.2f %e %g\n", pi, pi, pi, pi)
// 3.141593 3.14 3.141593e+00 3.141592653589793
s, r := "hello", 'A'
fmt.Printf("%s %q %c %U\n", s, s, r, r)
// hello "hello" A U+0041
type Person struct{ Name string; Age int }
p := Person{"John", 25}
fmt.Printf("%v\n%+v\n%#v\n", p, p, p)
// {John 25}
// {Name:John Age:25}
// main.Person{Name:"John", Age:25}8. Common Mistakes ⚠️
| Mistake | Problem | Fix |
|---|---|---|
string(65) expecting "65" | produces "A" (rune conversion) | use strconv.Itoa(65) |
int size assumption | int is 32-bit on 32-bit OS | use int64 when size matters |
| Implicit conversion | float64(x) + int(y) won’t compile | always convert explicitly |
float64 for money/finance | precision errors | use int cents or decimal library |
Comparing float64 with == | precision issues | use math.Abs(a-b) < epsilon |
| Forgetting zero values | assuming uninitialized = garbage | Go zeroes everything — use this intentionally |
9. Interview Cheat Sheet
Q: What is Go’s default integer type?
int— its size is platform-dependent (32 or 64 bits). For most code, useint. Useint64when you need guaranteed 64-bit width.
Q: What is the zero value of each type?
Numerics →
0,bool→false,string→"", pointers/slices/maps/channels →nil. Go always initialises — no garbage values.
Q: What is the difference between byte and rune?
byte=uint8(raw byte, 0–255).rune=int32(Unicode code point). Usebytefor binary data,runefor characters.
Q: Does Go do implicit type conversion?
No. All conversions must be explicit:
float64(i),int(f). Mixing types without conversion is a compile error.
Q: Why use float64 over float32?
float64is the default for all floating-point literals and math functions.float32has less precision and rarely saves meaningful memory in practice.