Like in many other languages structs in rust are a primitive for grouping together related fields of data.
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
When creating an instance of a struct it can be either shared or mutable. Rust doesn't allow marking individual fields as mutable. As with any expression we can construct a new instance of the struct as the last expression in the function body to implicitly return that new instance. This is a common pattern for constructors style functions in rust.
fn build_user(email: String, username: String) -> User {
User {
active: true,
username: username,
email: email,
sign_in_count: 1,
}
}
methods
A method is defined within the context of a struct, an enum, or a trait object.
Their first parameter is always self which represents the instance the method
is being called on. Methods can take ownership of self, borrow self
immutably, or borrow self mutably.
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
Rust supports automatic referencing and dereferencing so that when calling a method rust will automatically add in &, &mut, or * so object matches the signature of the method.
associated functions
All methods are considered associated functions because they are within the
impl block for a struct. You can create other associated functions which are
not methods. The most common of which is the "constructor pattern" which by
convention are often named new. The from function of String::from is an
associated function.
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
constructor naming
For a constructor that cannot fail the name new is usually appropriate. For
constructors which instead return a Result, the name build is better.
multiple impl blocks
A struct can have multiple impl blocks. This is sometimes useful with traits
and generics.
field init shorthand
When your function parameters and field names are exactly the same (such as in a constructor) rust allows a syntax that avoids repeating field names:
fn build_user(email: String, username: String) -> User {
User {
active: true,
username,
email,
sign_in_count: 1,
}
}
struct update syntax
When creating a new instance of a struct that is very similar to another instance you can use this syntax to only write out the differences. HOWEVER, this syntax will move any fields which do not implement the Copy trait. This means the original struct user1 cannot be used in full anymore:
let user1 = User {
active: true,
username: String::from("someusername123"),
email: String::from("someone@example.com"),
sign_in_count: 1,
};
let user2 = User {
email: String::from("another@example.com"),
..user1
};
tuple struct
Rust supports structs which look similar to tuples, but have the added meaning the struct name provides. Tuple structs are useful when you want to give the whole tuple a name and make the tuple a different type from other tuples, and when naming each field as in a regular struct would be verbose or redundant.
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
field-less structs
You can also define structs without any fields! These are called unit-like
structs because they behave similarly to the unit type (empty tuple).
Unit-like structs can be useful when you need to implement a trait on some type
but don’t have any data that you want to store in the type itself.
struct AlwaysEqual;
fn main() {
let subject = AlwaysEqual;
}
lifetime annotations in struct fields
We can define structs to hold references, but in that case we would need to add a lifetime annotation on every reference in the struct's definition:
struct ImportantExcept<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentense = novel.split('.').next().unwrap();
let i = ImportantExcept {
part: first_sentense,
};
}
This type annotation means instances of ImportantExcept cannot outlive the
reference it holds in its part field.