Introduction to Go's Type System
Why Go's Type System Matters
The Problem: Untyped languages let bugs hide. Verbose typing slows you down.
The Solution: Go's type system is static, strict, and minimal — no implicit conversions, no inheritance, just structs and interfaces. Type inference (`:=`) keeps it ergonomic.
Real Impact: You get the safety of static typing with the brevity of a dynamic language for declarations.
Real-World Analogy
Think of Go types as the gauges on a dashboard:
- var / := = two ways to install a gauge — explicit vs auto-detected
- Zero value = the default reading when nothing's set yet
- Type = what the gauge measures — fixed, never converts silently
- Named type = a labelled, purpose-built gauge (e.g. Celsius vs Fahrenheit)
- Interface = any gauge that implements the right contract
Go is a statically typed language with a simple yet powerful type system. Understanding types is fundamental to writing efficient and safe Go programs.
Go's Type Philosophy
- Static Typing: Types are checked at compile time
- Type Inference: Compiler can deduce types automatically
- No Implicit Conversions: Explicit conversions required
- Zero Values: All variables have a default zero value
Variable Declaration
Method 1: var Keyword
var name string = "Alice"
var age int = 30
var isActive bool = true
// Type inference
var city = "New York" // string inferred
// Declaration without initialization (zero value)
var count int // 0
var message string // ""
var done bool // false
Method 2: Short Declaration (:=)
// Inside functions only
name := "Bob"
age := 25
pi := 3.14159
// Multiple variables
x, y := 10, 20
width, height := getSize()
Constants
const Pi = 3.14159
const MaxUsers = 100
const AppName = "MyApp"
// Typed constants
const typedInt int = 42
// Constant expressions
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
)
Basic Types
Numeric Types
| Type | Size | Range |
|---|---|---|
int8 |
8 bits | -128 to 127 |
int16 |
16 bits | -32,768 to 32,767 |
int32 |
32 bits | -2,147,483,648 to 2,147,483,647 |
int64 |
64 bits | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
uint8 (byte) |
8 bits | 0 to 255 |
float32 |
32 bits | ±1.18e-38 to ±3.4e38 |
float64 |
64 bits | ±2.23e-308 to ±1.80e308 |
Type Conversion
var x int = 42
var y float64 = float64(x) // Explicit conversion
var z uint = uint(x)
// String conversion
import "strconv"
str := strconv.Itoa(42) // int to string
num, err := strconv.Atoi("42") // string to int
flt, err := strconv.ParseFloat("3.14", 64)
Custom Types
// Type definition
type UserID int
type Celsius float64
type Fahrenheit float64
// Using custom types
var uid UserID = 12345
var temp Celsius = 25.5
// Type methods
func (c Celsius) ToFahrenheit() Fahrenheit {
return Fahrenheit(c*9/5 + 32)
}
Zero Values
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // ""
var p *int // nil
var a []int // nil
var m map[string]int // nil
var ch chan int // nil
var fn func() // nil
var iface interface{} // nil
Type Aliases
// Type alias (same type)
type ByteSize = int64
// Type definition (new type)
type Duration int64
var size ByteSize = 1024 // Can use as int64
var dur Duration = 1000 // New type, needs conversion
Practice Exercises
Exercise 1: Temperature Converter
Create custom types for Celsius, Fahrenheit, and Kelvin with conversion methods between them.
Exercise 2: Safe Calculator
Build a calculator that handles division by zero and integer overflow safely.
Exercise 3: Type Detective
Write a function that identifies and prints the type of any variable using reflection.