Slices in Rust
In this lesson, you will learn about slices in Rust. Slices allow you to reference a portion of a collection without taking ownership of it.
Slices work closely with references and are commonly used with strings and arrays. They provide a safe and efficient way to access parts of data.
What Is a Slice?
A slice is a reference to a contiguous sequence of elements in a collection. Instead of copying data, slices borrow a portion of it.
Slices do not own the data they point to. They only reference existing data.
String Slices
String slices are the most common type of slice in Rust. They allow you to reference part of a string using a range.
let text = String::from("Rust Programming");
let part = &text[0..4];
println!("{}", part);
This slice references the first four bytes of the string.
Slice Syntax
Slices use the range syntax [start..end].
startis inclusiveendis exclusive
let s = String::from("Dataplexa");
let a = &s[..4]; // From start
let b = &s[4..]; // To end
let c = &s[..]; // Entire string
Why String Slices Use Bytes
Rust strings are UTF-8 encoded. This means characters can occupy more than one byte.
Because of this, slicing strings at invalid byte boundaries will cause a runtime panic.
// This may panic if slicing breaks UTF-8 boundaries
let s = String::from("Здравствуйте");
let slice = &s[0..2];
Always slice strings carefully when working with non-ASCII characters.
String Literals Are Slices
String literals have the type &str.
They are slices that point directly to program memory.
let msg: &str = "Hello Rust";
println!("{}", msg);
This is why functions often accept &str instead of &String.
Array Slices
Slices can also be created from arrays. Array slices allow you to borrow part of an array safely.
let numbers = [10, 20, 30, 40, 50];
let slice = &numbers[1..4];
println!("{:?}", slice);
This slice contains elements at indexes 1, 2, and 3.
Slices and Functions
Slices are commonly used as function parameters. They allow functions to work with data without owning it.
fn sum(values: &[i32]) -> i32 {
values.iter().sum()
}
fn main() {
let nums = [1, 2, 3, 4];
println!("{}", sum(&nums));
}
Mutable Slices
You can also create mutable slices to modify parts of a collection.
let mut arr = [1, 2, 3, 4];
let slice = &mut arr[1..3];
slice[0] = 10;
println!("{:?}", arr);
Rules for Slices
Slices follow the same borrowing rules as references:
- Multiple immutable slices are allowed
- Only one mutable slice is allowed at a time
- Mutable and immutable slices cannot coexist
Why Slices Are Important
Slices allow Rust programs to be:
- Efficient (no data copying)
- Memory safe
- Flexible when working with collections
📝 Practice Exercises
Exercise 1
Create a slice from a string and print it.
Exercise 2
Create an array slice containing three elements.
Exercise 3
Write a function that accepts a slice parameter.
Exercise 4
Modify part of an array using a mutable slice.
✅ Practice Answers
Answer 1
let s = String::from("Rustacean");
let part = &s[0..4];
println!("{}", part);
Answer 2
let arr = [5, 10, 15, 20, 25];
let slice = &arr[1..4];
Answer 3
fn print_all(values: &[i32]) {
for v in values {
println!("{}", v);
}
}
Answer 4
let mut nums = [1, 2, 3, 4];
let s = &mut nums[0..2];
s[0] = 99;
What’s Next?
Now that you understand slices, the next lesson will introduce lifetimes, which explain how long references and slices remain valid.