Mojo Structs
A struct bundles related data and the functions that operate on that data into one named unit. Instead of tracking a person's name, age, and email in three separate variables, you define a Person struct and store everything together. Mojo structs are the primary way to create custom data types.
The Blueprint Analogy
Struct Definition (Blueprint)
┌────────────────────────────────┐
│ struct Car: │
│ var make: String │
│ var model: String │
│ var year: Int │
└────────────────────────────────┘
│ │ │
▼ ▼ ▼
Car instance Car instance Car instance
make="Toyota" make="Ford" make="BMW"
model="Corolla" model="Focus" model="X5"
year=2022 year=2019 year=2024
One blueprint → unlimited instances
Defining a Struct
struct Point:
var x: Float64
var y: Float64
fn __init__(inout self, x: Float64, y: Float64):
self.x = x
self.y = y
Key Parts
struct Point: ← struct keyword + name
var x: Float64 ← field (member variable)
var y: Float64 ← field
fn __init__(inout self, x, y): ← initializer
self.x = x ← store argument into field
self.y = y
The __init__ method runs automatically when you create a new instance. The self parameter refers to the specific instance being created — it is how the function knows which object's fields to fill.
Creating Instances
fn main():
var origin = Point(0.0, 0.0)
var corner = Point(5.0, 3.0)
print(origin.x, origin.y) # 0.0 0.0
print(corner.x, corner.y) # 5.0 3.0
A Practical Struct: BankAccount
struct BankAccount:
var owner: String
var balance: Float64
fn __init__(inout self, owner: String, opening_balance: Float64):
self.owner = owner
self.balance = opening_balance
fn deposit(inout self, amount: Float64):
self.balance += amount
print(self.owner, "deposited", amount, "| Balance:", self.balance)
fn withdraw(inout self, amount: Float64):
if amount > self.balance:
print("Insufficient funds")
else:
self.balance -= amount
print(self.owner, "withdrew", amount, "| Balance:", self.balance)
fn show_balance(self):
print(self.owner, "balance:", self.balance)
fn main():
var acc = BankAccount("Aisha", 1000.0)
acc.deposit(500.0) # Aisha deposited 500.0 | Balance: 1500.0
acc.withdraw(200.0) # Aisha withdrew 200.0 | Balance: 1300.0
acc.withdraw(2000.0) # Insufficient funds
acc.show_balance() # Aisha balance: 1300.0
The self Parameter
Every method inside a struct receives self as its first parameter. self is the current instance — it lets the method access and modify that specific instance's fields.
acc.deposit(500.0)
│ │
│ └── argument 'amount'
└── becomes 'self' inside the method
Inside deposit:
self.balance += amount
↑ ↑
acc's balance 500.0
When a method only reads fields, use fn method(self):. When a method modifies fields, use fn method(inout self):.
Struct Memory Layout
struct Point: Memory layout for Point(3.0, 7.0):
var x: Float64 → [ 3.0 ][ 7.0 ]
var y: Float64 8 bytes 8 bytes
total: 16 bytes on stack
Structs in Mojo store data on the stack by default —
no pointer indirection, no garbage collection overhead.
Immutable vs Mutable Methods
struct Temperature:
var celsius: Float64
fn __init__(inout self, c: Float64):
self.celsius = c
# Read-only — does not modify the struct
fn to_fahrenheit(self) -> Float64:
return self.celsius * 9.0 / 5.0 + 32.0
# Mutating — changes the struct's field
fn set(inout self, c: Float64):
self.celsius = c
fn main():
var temp = Temperature(100.0)
print(temp.to_fahrenheit()) # 212.0
temp.set(0.0)
print(temp.to_fahrenheit()) # 32.0
Structs vs Python Classes
Feature | Mojo Struct | Python Class -------------------------|---------------------|------------------ Memory layout | Fixed, on stack | Heap, dynamic Field types | Must be declared | No types required Performance | C-level speed | Interpreted speed Inheritance | Via Traits | Direct Dynamic attributes | Not supported | Supported
Key Takeaways
A struct groups related fields and methods into one custom type. The __init__ method initializes the struct when you create an instance. Use self to access the current instance's fields. Read-only methods use self; mutating methods use inout self. Mojo structs store data on the stack, giving them C-level performance with Python-like readability.
