&self = immutable borrow, multiple allowed, read-only. &mut self = mutable borrow, exclusive, read-write. The borrow checker enforces these rules to prevent data races.
&self — shared read access:
1struct Stack<T> {2 elements: Vec<T>,3}45impl<T: std::fmt::Debug> Stack<T> {6 fn peek(&self) -> Option<&T> {7 self.elements.last()8 }910 fn len(&self) -> usize {11 self.elements.len()12 }1314 fn is_empty(&self) -> bool {15 self.elements.is_empty()16 }17}1819let stack = Stack { elements: vec![1, 2, 3] };20println!("Top: {:?}", stack.peek()); // Some(3)21println!("Len: {}", stack.len()); // 3
&mut self — exclusive write access:
1impl<T> Stack<T> {2 fn push(&mut self, item: T) {3 self.elements.push(item);4 }56 fn pop(&mut self) -> Option<T> {7 self.elements.pop()8 }910 fn clear(&mut self) {11 self.elements.clear();12 }13}1415let mut stack = Stack { elements: vec![1, 2, 3] };16stack.push(4); // push: &mut self17stack.pop(); // pop: &mut self
When to use &self:
When to use &mut self:
Common mistakes:
let mut for &mut self methods.