References & Slices
References borrow data without taking ownership. Slices (&[T], &str) are borrowed views into contiguous sequences with runtime length.
Search across all documentation pages
References borrow data without taking ownership. Slices (&[T], &str) are borrowed views into contiguous sequences with runtime length.
fn first_word(s: &str) -> &str {
match s.find(' ') {
Some(i) => &s[..i],
None => s,
}
}
fn main() {
let sentence = String::from("hello world");
println!("{}", first_word(&sentence));
}When to reach for this: Function parameters that only read data, substring extraction, and passing array views without copying.
fn sum_slice(nums: &[i32]) -> i32 {
nums.iter().sum()
}
fn window(data: &[i32], start: usize, len: usize) -> Option<&[i32]> {
data.get(start..start + len)
}
fn main() {
let arr = [10, 20, 30, 40];
println!("sum={}", sum_slice(&arr));
println!("{:?}", window(&arr, 1, 2));
}What this demonstrates:
&[i32] accepts arrays and Vec via coercionstart..end on arrays and strings.get(range) returns Option instead of panicking&str from &String via deref coercion| Type | Access | Count at once |
|---|---|---|
&T | Shared read | Many |
&mut T | Exclusive write | One (no & simultaneously) |
let s = String::from("hello");
let slice: &str = &s[0..2]; // "he" - byte indicesUTF-8 means byte indices must fall on char boundaries or slicing panics.
let a = [1, 2, 3, 4];
let mid: &[i32] = &a[1..3]; // [2, 3]fn head(tail: &[i32]) -> Option<(&i32, &[i32])> {
tail.split_first()
}.chars() or unicode-segmentation for graphemes.String - Lifetime error. Fix: Return owned String or take owner as parameter.&Vec<T> with &[T] - Prefer &[T] in APIs. Fix: Use slice form; &vec coerces automatically.&mut to overlapping ranges fails. Fix: Split with split_at_mut.arr[99] panics. Fix: Use .get(99).| Alternative | Use When | Don't Use When |
|---|---|---|
Owned String/Vec | Caller transfers ownership | Read-only inspection suffices |
Cow<'a, str> | Maybe borrow, maybe allocate | Ownership always clear |
| Indices + length | FFI interop | Safe Rust APIs |
| Iterators | Lazy traversal | Random access needed |
&String coerces to &str, &Vec<T> to &[T] at function call sites when the target expects a slice.
Yes. &[] and &s[0..0] are valid empty slices.
len() is usize. Slices cannot exceed the underlying allocation.
Slices are references (fat pointers). Elements are not copied.
Yes. slice[0] = 1 mutates the underlying array or Vec.
Low-level pointer to first element. Used in unsafe/FFI, not typical application code.
slice.to_vec() for owned Vec. slice.to_owned() when T: Clone.
Not in safe Rust. Use Option<&str> for absence.
Slice/str fat pointer stores data pointer plus length (two words).
&str in a return type needs a lifetime tied to input. See the Ownership section.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026