&self = immutable borrow (shared, read-only). &mut self = mutable borrow (exclusive, read-write). The borrow checker enforces these rules to prevent data races.
&self — shared read access:
1struct Logger {2 entries: Vec<String>,3}45impl Logger {6 fn last_entry(&self) -> Option<&str> {7 self.entries.last().map(|s| s.as_str())8 }910 fn entries_since(&self, n: usize) -> &[String] {11 &self.entries[n..]12 }1314 fn total_entries(&self) -> usize {15 self.entries.len()16 }17}1819let logger = Logger { entries: vec!["start".into(), "end".into()] };20println!("{:?}", logger.last_entry()); // Some("end")21println!("Total: {}", logger.total_entries()); // 2
&mut self — exclusive write access:
1impl Logger {2 fn log(&mut self, message: String) {3 self.entries.push(message);4 }56 fn truncate(&mut self, keep_last: usize) {7 let len = self.entries.len();8 if len > keep_last {9 self.entries.drain(..len - keep_last);10 }11 }1213 fn clear(&mut self) {14 self.entries.clear();15 }16}1718let mut logger = Logger { entries: vec![] };19logger.log("event1".into());20logger.truncate(10);
When to use &self:
When to use &mut self:
Common mistakes:
let mut for &mut self methods.