Rust Lesson 16 – Slices | Dataplexa

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].

  • start is inclusive
  • end is 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.