The ownership track ended on a frustration: to let a function read your data, you had to give it away and get it back. References fix that. A reference lets you use a value without owning it — borrow it, look, and let it go automatically.
The & operator
&s creates a reference to s without taking ownership. Pass &s to a function and the function borrows the value: it can read it, but ownership stays with the caller. When the reference goes out of scope, nothing is dropped — you only borrowed it.
Borrowing in function signatures
A parameter of type &String (or better, &str) says 'I want to read this, not own it.' The caller keeps the value after the call returns. This is the default you'll reach for constantly: take a reference unless you genuinely need ownership.
References are not the dangerous kind of pointer
A Rust reference is guaranteed to point at valid data for as long as it exists — the compiler proves it. There's no null reference, no dangling reference, no 'is this still alive?' A reference is a promise the borrow checker enforces, not a raw address you have to babysit.