&self = immutable borrow, multiple allowed, read-only. &mut self = mutable borrow, exclusive, read-write. The borrow checker enforces these rules at compile time to prevent data races.
&self — shared read access:
1struct User {2 name: String,3 email: String,4 active: bool,5}67impl User {8 fn name(&self) -> &str {9 &self.name10 }1112 fn is_active(&self) -> bool {13 self.active14 }1516 fn display(&self) {17 println!("{} ({})", self.name, if self.active { "active" } else { "inactive" });18 }19}2021let user = User { name: "Alice".into(), email: "a@b.com".into(), active: true };22user.display(); // &self23let n = user.name(); // Another &self — OK!
&mut self — exclusive write access:
1impl User {2 fn deactivate(&mut self) {3 self.active = false;4 }56 fn update_email(&mut self, email: String) {7 self.email = email;8 }910 fn activate(&mut self) {11 self.active = true;12 }13}1415let mut user = User { name: "Bob".into(), email: "b@c.com".into(), active: true };16user.deactivate(); // &mut self17user.update_email("new@email.com".into());
When to use &self:
When to use &mut self:
Common mistakes:
let mut for &mut self methods.