Structs
How to create custom types with structs.
Structs
A struct allows us to create custom types that package multiple values together.
Basic Struct Definition
RUSTstruct User { username: String, email: String, sign_in_count: u64, active: bool, }
Creating Struct Instances
RUSTlet user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, };
Accessing Fields
RUSTprintln!("{}", user1.email); user1.sign_in_count += 1;
Mutable Struct
RUSTlet mut user1 = User { /* ... */ }; user1.email = String::from("anotheremail@example.com");
Field Init Shorthand
RUSTfn build_user(email: String, username: String) -> User { User { email, // instead of email: email username, // instead of username: username active: true, sign_in_count: 1, } }
Tuple Structs
RUSTstruct Color(i32, i32, i32); let black = Color(0, 0, 0);
Unit-like Structs
RUSTstruct AlwaysEqual; let subject = AlwaysEqual;
Code Examples
Basic Struct
Struct definition and usage
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
println!("User: {}", user1.username);
println!("Email: {}", user1.email);
}Explanation:
A struct allows us to package related data together. Fields are accessed with dot notation.
Mutable Struct
Modifying a struct
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
user1.sign_in_count += 1;
println!("Sign-in count: {}", user1.sign_in_count);
}Explanation:
To modify a struct, the variable must be `mut`. Then any field can be modified.
Tuple Struct
Using tuple structs
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
println!("Color RGB: ({}, {}, {})", black.0, black.1, black.2);
}Explanation:
Tuple structs are useful when we want a distinct type but don't need field names. Elements are accessed by index.
Blockchain: Transaction Struct
Using structs for blockchain transactions
struct Transaction {
from: String,
to: String,
amount: u64,
fee: u64,
nonce: u64,
}
fn main() {
let tx = Transaction {
from: String::from("0xAlice"),
to: String::from("0xBob"),
amount: 100,
fee: 10,
nonce: 1,
};
println!("Transaction:");
println!(" From: {}", tx.from);
println!(" To: {}", tx.to);
println!(" Amount: {} tokens", tx.amount);
println!(" Fee: {} tokens", tx.fee);
println!(" Total: {} tokens", tx.amount + tx.fee);
}Explanation:
Structs are perfect for representing blockchain transactions. They group related data (sender, receiver, amount, etc.) into a single type.
Blockchain: Account Struct
Representing blockchain accounts with structs
struct Account {
address: String,
balance: u64,
nonce: u64,
is_contract: bool,
}
impl Account {
fn new(address: String) -> Self {
Account {
address,
balance: 0,
nonce: 0,
is_contract: false,
}
}
fn display(&self) {
let account_type = if self.is_contract { "Contract" } else { "Wallet" };
println!("{} Account: {}", account_type, self.address);
println!(" Balance: {} tokens", self.balance);
println!(" Nonce: {}", self.nonce);
}
}
fn main() {
let mut account = Account::new(String::from("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"));
account.balance = 1000;
account.display();
}Explanation:
Account structs store blockchain account information. Methods can be added to structs using impl blocks for functionality like displaying account info.
Exercises
Creating a Struct
Create a Rectangle struct with width and height fields!
Starter Code:
fn main() {
}Blockchain: Create Transaction
Create a Transaction struct for blockchain!
Starter Code:
fn main() {
}